Index: compiler-rt/trunk/lib/asan/tests/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/asan/tests/CMakeLists.txt +++ compiler-rt/trunk/lib/asan/tests/CMakeLists.txt @@ -74,10 +74,6 @@ -fsanitize=address "-fsanitize-blacklist=${ASAN_BLACKLIST_FILE}" ) -if(CAN_TARGET_x86_64 OR CAN_TARGET_i386) - list(APPEND ASAN_UNITTEST_INSTRUMENTED_CFLAGS -mllvm -asan-instrument-assembly) -endif() - if(NOT MSVC) list(APPEND ASAN_UNITTEST_COMMON_LINK_FLAGS --driver-mode=g++) endif() @@ -142,7 +138,6 @@ set(ASAN_INST_TEST_SOURCES ${COMPILER_RT_GTEST_SOURCE} - asan_asm_test.cc asan_globals_test.cc asan_interface_test.cc asan_internal_interface_test.cc Index: compiler-rt/trunk/lib/asan/tests/asan_asm_test.cc =================================================================== --- compiler-rt/trunk/lib/asan/tests/asan_asm_test.cc +++ compiler-rt/trunk/lib/asan/tests/asan_asm_test.cc @@ -1,273 +0,0 @@ -//===-- asan_asm_test.cc --------------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is a part of AddressSanitizer, an address sanity checker. -// -//===----------------------------------------------------------------------===// -#include "asan_test_utils.h" - -#if defined(__linux__) && \ - (!defined(ASAN_SHADOW_SCALE) || ASAN_SHADOW_SCALE == 3) - -// Assembly instrumentation is broken on x86 Android (x86 + PIC + shared runtime -// library). See https://github.com/google/sanitizers/issues/353 -#if defined(__x86_64__) || \ - (defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)) - -#include - -namespace { - -template void asm_write(T *ptr, T val); -template T asm_read(T *ptr); -template void asm_rep_movs(T *dst, T *src, size_t n); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#if defined(__x86_64__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> \ - void asm_rep_movs(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : "+D"(dst), "+S"(src), "+c"(size) \ - : \ - : "memory"); \ - } - -DECLARE_ASM_WRITE(U8, "8", "movq", "r"); -DECLARE_ASM_READ(U8, "8", "movq", "=r"); -DECLARE_ASM_REP_MOVS(U8, "movsq"); - -} // End of anonymous namespace - -#endif // defined(__x86_64__) - -#if defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__) - -namespace { - -#define DECLARE_ASM_WRITE(Type, Size, Mov, Reg) \ -template<> void asm_write(Type *ptr, Type val) { \ - __asm__( \ - Mov " %[val], (%[ptr]) \n\t" \ - : \ - : [ptr] "r" (ptr), [val] Reg (val) \ - : "memory" \ - ); \ -} - -#define DECLARE_ASM_READ(Type, Size, Mov, Reg) \ -template<> Type asm_read(Type *ptr) { \ - Type res; \ - __asm__( \ - Mov " (%[ptr]), %[res] \n\t" \ - : [res] Reg (res) \ - : [ptr] "r" (ptr) \ - : "memory" \ - ); \ - return res; \ -} - -#define DECLARE_ASM_REP_MOVS(Type, Movs) \ - template <> \ - void asm_rep_movs(Type * dst, Type * src, size_t size) { \ - __asm__("rep " Movs " \n\t" \ - : "+D"(dst), "+S"(src), "+c"(size) \ - : \ - : "memory"); \ - } - -} // End of anonymous namespace - -#endif // defined(__i386__) && defined(__SSE2__) - -#if defined(__x86_64__) || \ - (defined(__i386__) && defined(__SSE2__) && !defined(__ANDROID__)) - -namespace { - -DECLARE_ASM_WRITE(U1, "1", "movb", "r"); -DECLARE_ASM_WRITE(U2, "2", "movw", "r"); -DECLARE_ASM_WRITE(U4, "4", "movl", "r"); -DECLARE_ASM_WRITE(__m128i, "16", "movaps", "x"); - -DECLARE_ASM_READ(U1, "1", "movb", "=r"); -DECLARE_ASM_READ(U2, "2", "movw", "=r"); -DECLARE_ASM_READ(U4, "4", "movl", "=r"); -DECLARE_ASM_READ(__m128i, "16", "movaps", "=x"); - -DECLARE_ASM_REP_MOVS(U1, "movsb"); -DECLARE_ASM_REP_MOVS(U2, "movsw"); -DECLARE_ASM_REP_MOVS(U4, "movsl"); - -template void TestAsmWrite(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_write(&buf[1], static_cast(0)), DeathPattern); - T var = 0x12; - asm_write(&var, static_cast(0x21)); - ASSERT_EQ(static_cast(0x21), var); - delete buf; -} - -template<> void TestAsmWrite<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - __m128i val = _mm_set1_epi16(0x1234); - EXPECT_DEATH(asm_write<__m128i>((__m128i*) p, val), DeathPattern); - __m128i var = _mm_set1_epi16(0x4321); - asm_write(&var, val); - ASSERT_EQ(0x1234, _mm_extract_epi16(var, 0)); - delete [] buf; -} - -template void TestAsmRead(const char *DeathPattern) { - T *buf = new T; - EXPECT_DEATH(asm_read(&buf[1]), DeathPattern); - T var = 0x12; - ASSERT_EQ(static_cast(0x12), asm_read(&var)); - delete buf; -} - -template<> void TestAsmRead<__m128i>(const char *DeathPattern) { - char *buf = new char[16]; - char *p = buf + 16; - if (((uintptr_t) p % 16) != 0) - p = buf + 8; - assert(((uintptr_t) p % 16) == 0); - EXPECT_DEATH(asm_read<__m128i>((__m128i*) p), DeathPattern); - __m128i val = _mm_set1_epi16(0x1234); - ASSERT_EQ(0x1234, _mm_extract_epi16(asm_read(&val), 0)); - delete [] buf; -} - -U4 AsmLoad(U4 *a) { - U4 r; - __asm__("movl (%[a]), %[r] \n\t" : [r] "=r" (r) : [a] "r" (a) : "memory"); - return r; -} - -void AsmStore(U4 r, U4 *a) { - __asm__("movl %[r], (%[a]) \n\t" : : [a] "r" (a), [r] "r" (r) : "memory"); -} - -template -void TestAsmRepMovs(const char *DeathPatternRead, - const char *DeathPatternWrite) { - T src_good[4] = { 0x0, 0x1, 0x2, 0x3 }; - T dst_good[4] = {}; - asm_rep_movs(dst_good, src_good, 4); - ASSERT_EQ(static_cast(0x0), dst_good[0]); - ASSERT_EQ(static_cast(0x1), dst_good[1]); - ASSERT_EQ(static_cast(0x2), dst_good[2]); - ASSERT_EQ(static_cast(0x3), dst_good[3]); - - T dst_bad[3]; - EXPECT_DEATH(asm_rep_movs(dst_bad, src_good, 4), DeathPatternWrite); - - T src_bad[3] = { 0x0, 0x1, 0x2 }; - EXPECT_DEATH(asm_rep_movs(dst_good, src_bad, 4), DeathPatternRead); - - T* dp = dst_bad + 4; - T* sp = src_bad + 4; - asm_rep_movs(dp, sp, 0); -} - -} // End of anonymous namespace - -TEST(AddressSanitizer, asm_load_store) { - U4* buf = new U4[2]; - EXPECT_DEATH(AsmLoad(&buf[3]), "READ of size 4"); - EXPECT_DEATH(AsmStore(0x1234, &buf[3]), "WRITE of size 4"); - delete [] buf; -} - -TEST(AddressSanitizer, asm_rw) { - TestAsmWrite("WRITE of size 1"); - TestAsmWrite("WRITE of size 2"); - TestAsmWrite("WRITE of size 4"); -#if defined(__x86_64__) - TestAsmWrite("WRITE of size 8"); -#endif // defined(__x86_64__) - TestAsmWrite<__m128i>("WRITE of size 16"); - - TestAsmRead("READ of size 1"); - TestAsmRead("READ of size 2"); - TestAsmRead("READ of size 4"); -#if defined(__x86_64__) - TestAsmRead("READ of size 8"); -#endif // defined(__x86_64__) - TestAsmRead<__m128i>("READ of size 16"); -} - -TEST(AddressSanitizer, asm_flags) { - long magic = 0x1234; - long r = 0x0; - -#if defined(__x86_64__) && !defined(__ILP32__) - __asm__("xorq %%rax, %%rax \n\t" - "movq (%[p]), %%rax \n\t" - "sete %%al \n\t" - "movzbq %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "rax", "memory"); -#else - __asm__("xorl %%eax, %%eax \n\t" - "movl (%[p]), %%eax \n\t" - "sete %%al \n\t" - "movzbl %%al, %[r] \n\t" - : [r] "=r"(r) - : [p] "r"(&magic) - : "eax", "memory"); -#endif // defined(__x86_64__) && !defined(__ILP32__) - - ASSERT_EQ(0x1, r); -} - -TEST(AddressSanitizer, asm_rep_movs) { - TestAsmRepMovs("READ of size 1", "WRITE of size 1"); - TestAsmRepMovs("READ of size 2", "WRITE of size 2"); - TestAsmRepMovs("READ of size 4", "WRITE of size 4"); -#if defined(__x86_64__) - TestAsmRepMovs("READ of size 8", "WRITE of size 8"); -#endif // defined(__x86_64__) -} - -#endif // defined(__x86_64__) || (defined(__i386__) && defined(__SSE2__)) - -#endif // defined(__linux__) Index: compiler-rt/trunk/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc =================================================================== --- compiler-rt/trunk/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc +++ compiler-rt/trunk/test/asan/TestCases/Linux/asan-asm-stacktrace-test.cc @@ -1,33 +0,0 @@ -// Check that a stack unwinding algorithm works corretly even with the assembly -// instrumentation. - -// REQUIRES: x86_64-target-arch, shadow-scale-3 -// RUN: %clangxx_asan -g -O1 %s -fno-inline-functions -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -g -O1 %s -fno-inline-functions -fomit-frame-pointer -momit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s -// RUN: %clangxx_asan -g0 -O1 %s -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-exceptions -fno-inline-functions -fomit-frame-pointer -momit-leaf-frame-pointer -mllvm -asan-instrument-assembly -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-nounwind - -#include - -// CHECK: READ of size 4 -// CHECK-NEXT: {{#0 0x[0-9a-fA-F]+ in foo}} -// CHECK-NEXT: {{#1 0x[0-9a-fA-F]+ in main}} - -// CHECK-nounwind: READ of size 4 -// CHECK-nounwind-NEXT: {{#0 0x[0-9a-fA-F]+ in foo}} - -__attribute__((noinline)) int foo(size_t n, int *buffer) { - int r; - __asm__("movl (%[buffer], %[n], 4), %[r] \n\t" - : [r] "=r"(r) - : [buffer] "r"(buffer), [n] "r"(n) - : "memory"); - return r; -} - -int main() { - const size_t n = 16; - int *buffer = new int[n]; - foo(n, buffer); - delete[] buffer; - return 0; -} Index: llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h =================================================================== --- llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -384,9 +384,6 @@ 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: llvm/trunk/include/llvm/MC/MCTargetOptions.h =================================================================== --- llvm/trunk/include/llvm/MC/MCTargetOptions.h +++ llvm/trunk/include/llvm/MC/MCTargetOptions.h @@ -38,9 +38,6 @@ AsmInstrumentationAddress }; - /// Enables AddressSanitizer instrumentation at machine level. - bool SanitizeAddress : 1; - bool MCRelaxAll : 1; bool MCNoExecStack : 1; bool MCFatalWarnings : 1; Index: llvm/trunk/include/llvm/MC/MCTargetOptionsCommandFlags.inc =================================================================== --- llvm/trunk/include/llvm/MC/MCTargetOptionsCommandFlags.inc +++ llvm/trunk/include/llvm/MC/MCTargetOptionsCommandFlags.inc @@ -18,15 +18,6 @@ #include "llvm/Support/CommandLine.h" using namespace llvm; -static cl::opt AsmInstrumentation( - "asm-instrumentation", cl::desc("Instrumentation of inline assembly and " - "assembly source files"), - cl::init(MCTargetOptions::AsmInstrumentationNone), - cl::values(clEnumValN(MCTargetOptions::AsmInstrumentationNone, "none", - "no instrumentation at all"), - clEnumValN(MCTargetOptions::AsmInstrumentationAddress, "address", - "instrument instructions with memory arguments"))); - static cl::opt RelaxAll("mc-relax-all", cl::desc("When used with filetype=obj, " "relax all fixups in the emitted object file")); @@ -62,8 +53,6 @@ static MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; - Options.SanitizeAddress = - (AsmInstrumentation == MCTargetOptions::AsmInstrumentationAddress); Options.MCRelaxAll = RelaxAll; Options.MCIncrementalLinkerCompatible = IncrementalLinkerCompatible; Options.MCPIECopyRelocations = PIECopyRelocations; Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -157,10 +157,6 @@ // assembly. if (Dialect == InlineAsm::AD_Intel) Parser->getLexer().setLexMasmIntegers(true); - if (MF) { - const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); - TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); - } emitInlineAsmStart(); // Don't implicitly switch to the text section before the asm. @@ -527,11 +523,6 @@ else EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS); - // Reset SanitizeAddress based on the function's attribute. - MCTargetOptions MCOptions = TM.Options.MCOptions; - MCOptions.SanitizeAddress = - MF->getFunction().hasFnAttribute(Attribute::SanitizeAddress); - // Emit warnings if we use reserved registers on the clobber list, as // that might give surprising results. std::vector RestrRegs; @@ -570,7 +561,7 @@ SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note); } - EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD, + EmitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD, MI->getInlineAsmDialect()); // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't Index: llvm/trunk/lib/MC/MCTargetOptions.cpp =================================================================== --- llvm/trunk/lib/MC/MCTargetOptions.cpp +++ llvm/trunk/lib/MC/MCTargetOptions.cpp @@ -12,12 +12,11 @@ using namespace llvm; MCTargetOptions::MCTargetOptions() - : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false), - MCFatalWarnings(false), MCNoWarn(false), MCNoDeprecatedWarn(false), - MCSaveTempLabels(false), MCUseDwarfDirectory(false), - MCIncrementalLinkerCompatible(false), MCPIECopyRelocations(false), - ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), - PreserveAsmComments(true) {} + : MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false), + MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false), + MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false), + MCPIECopyRelocations(false), ShowMCEncoding(false), ShowMCInst(false), + AsmVerbose(false), PreserveAsmComments(true) {} StringRef MCTargetOptions::getABIName() const { return ABIName; Index: llvm/trunk/lib/Target/X86/AsmParser/CMakeLists.txt =================================================================== --- llvm/trunk/lib/Target/X86/AsmParser/CMakeLists.txt +++ llvm/trunk/lib/Target/X86/AsmParser/CMakeLists.txt @@ -1,4 +1,3 @@ add_llvm_library(LLVMX86AsmParser - X86AsmInstrumentation.cpp X86AsmParser.cpp ) Index: llvm/trunk/lib/Target/X86/AsmParser/X86AsmInstrumentation.h =================================================================== --- llvm/trunk/lib/Target/X86/AsmParser/X86AsmInstrumentation.h +++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmInstrumentation.h @@ -1,65 +0,0 @@ -//===- X86AsmInstrumentation.h - Instrument X86 inline assembly -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86ASMINSTRUMENTATION_H -#define LLVM_LIB_TARGET_X86_ASMPARSER_X86ASMINSTRUMENTATION_H - -#include "llvm/ADT/SmallVector.h" -#include - -namespace llvm { - -class MCContext; -class MCInst; -class MCInstrInfo; -class MCParsedAsmOperand; -class MCStreamer; -class MCSubtargetInfo; -class MCTargetOptions; -class X86AsmInstrumentation; - -X86AsmInstrumentation * -CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, - const MCContext &Ctx, - const MCSubtargetInfo *&STI); - -class X86AsmInstrumentation { -public: - virtual ~X86AsmInstrumentation(); - - // Sets frame register corresponding to a current frame. - void SetInitialFrameRegister(unsigned RegNo) { - InitialFrameReg = RegNo; - } - - // Tries to instrument and emit instruction. - virtual void InstrumentAndEmitInstruction( - const MCInst &Inst, - SmallVectorImpl> &Operands, - MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); - -protected: - friend X86AsmInstrumentation * - CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, - const MCContext &Ctx, - const MCSubtargetInfo *&STI); - - X86AsmInstrumentation(const MCSubtargetInfo *&STI); - - unsigned GetFrameRegGeneric(const MCContext &Ctx, MCStreamer &Out); - - void EmitInstruction(MCStreamer &Out, const MCInst &Inst); - - const MCSubtargetInfo *&STI; - - unsigned InitialFrameReg = 0; -}; - -} // end namespace llvm - -#endif // LLVM_LIB_TARGET_X86_ASMPARSER_X86ASMINSTRUMENTATION_H Index: llvm/trunk/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp =================================================================== --- llvm/trunk/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp +++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp @@ -1,1087 +0,0 @@ -//===-- X86AsmInstrumentation.cpp - Instrument X86 inline assembly --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "X86AsmInstrumentation.h" -#include "MCTargetDesc/X86MCTargetDesc.h" -#include "X86Operand.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDwarf.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCInstBuilder.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCParser/MCParsedAsmOperand.h" -#include "llvm/MC/MCParser/MCTargetAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCTargetOptions.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/SMLoc.h" -#include -#include -#include -#include -#include -#include - -// Following comment describes how assembly instrumentation works. -// Currently we have only AddressSanitizer instrumentation, but we're -// planning to implement MemorySanitizer for inline assembly too. If -// you're not familiar with AddressSanitizer algorithm, please, read -// https://github.com/google/sanitizers/wiki/AddressSanitizerAlgorithm -// -// When inline assembly is parsed by an instance of X86AsmParser, all -// instructions are emitted via EmitInstruction method. That's the -// place where X86AsmInstrumentation analyzes an instruction and -// decides, whether the instruction should be emitted as is or -// instrumentation is required. The latter case happens when an -// instruction reads from or writes to memory. Now instruction opcode -// is explicitly checked, and if an instruction has a memory operand -// (for instance, movq (%rsi, %rcx, 8), %rax) - it should be -// instrumented. There're also exist instructions that modify -// memory but don't have an explicit memory operands, for instance, -// movs. -// -// Let's consider at first 8-byte memory accesses when an instruction -// has an explicit memory operand. In this case we need two registers - -// AddressReg to compute address of a memory cells which are accessed -// and ShadowReg to compute corresponding shadow address. So, we need -// to spill both registers before instrumentation code and restore them -// after instrumentation. Thus, in general, instrumentation code will -// look like this: -// PUSHF # Store flags, otherwise they will be overwritten -// PUSH AddressReg # spill AddressReg -// PUSH ShadowReg # spill ShadowReg -// LEA MemOp, AddressReg # compute address of the memory operand -// MOV AddressReg, ShadowReg -// SHR ShadowReg, 3 -// # ShadowOffset(AddressReg >> 3) contains address of a shadow -// # corresponding to MemOp. -// CMP ShadowOffset(ShadowReg), 0 # test shadow value -// JZ .Done # when shadow equals to zero, everything is fine -// MOV AddressReg, RDI -// # Call __asan_report function with AddressReg as an argument -// CALL __asan_report -// .Done: -// POP ShadowReg # Restore ShadowReg -// POP AddressReg # Restore AddressReg -// POPF # Restore flags -// -// Memory accesses with different size (1-, 2-, 4- and 16-byte) are -// handled in a similar manner, but small memory accesses (less than 8 -// byte) require an additional ScratchReg, which is used for shadow value. -// -// If, suppose, we're instrumenting an instruction like movs, only -// contents of RDI, RDI + AccessSize * RCX, RSI, RSI + AccessSize * -// RCX are checked. In this case there're no need to spill and restore -// AddressReg , ShadowReg or flags four times, they're saved on stack -// just once, before instrumentation of these four addresses, and restored -// at the end of the instrumentation. -// -// There exist several things which complicate this simple algorithm. -// * Instrumented memory operand can have RSP as a base or an index -// register. So we need to add a constant offset before computation -// of memory address, since flags, AddressReg, ShadowReg, etc. were -// already stored on stack and RSP was modified. -// * Debug info (usually, DWARF) should be adjusted, because sometimes -// RSP is used as a frame register. So, we need to select some -// register as a frame register and temprorary override current CFA -// register. - -using namespace llvm; - -static cl::opt ClAsanInstrumentAssembly( - "asan-instrument-assembly", - cl::desc("instrument assembly with AddressSanitizer checks"), cl::Hidden, - cl::init(false)); - -static const int64_t MinAllowedDisplacement = - std::numeric_limits::min(); -static const int64_t MaxAllowedDisplacement = - std::numeric_limits::max(); - -static int64_t ApplyDisplacementBounds(int64_t Displacement) { - return std::max(std::min(MaxAllowedDisplacement, Displacement), - MinAllowedDisplacement); -} - -static void CheckDisplacementBounds(int64_t Displacement) { - assert(Displacement >= MinAllowedDisplacement && - Displacement <= MaxAllowedDisplacement); -} - -static bool IsStackReg(unsigned Reg) { - return Reg == X86::RSP || Reg == X86::ESP; -} - -static bool IsSmallMemAccess(unsigned AccessSize) { return AccessSize < 8; } - -namespace { - -class X86AddressSanitizer : public X86AsmInstrumentation { -public: - struct RegisterContext { - private: - enum RegOffset { - REG_OFFSET_ADDRESS = 0, - REG_OFFSET_SHADOW, - REG_OFFSET_SCRATCH - }; - - public: - RegisterContext(unsigned AddressReg, unsigned ShadowReg, - unsigned ScratchReg) { - BusyRegs.push_back(convReg(AddressReg, 64)); - BusyRegs.push_back(convReg(ShadowReg, 64)); - BusyRegs.push_back(convReg(ScratchReg, 64)); - } - - unsigned AddressReg(unsigned Size) const { - return convReg(BusyRegs[REG_OFFSET_ADDRESS], Size); - } - - unsigned ShadowReg(unsigned Size) const { - return convReg(BusyRegs[REG_OFFSET_SHADOW], Size); - } - - unsigned ScratchReg(unsigned Size) const { - return convReg(BusyRegs[REG_OFFSET_SCRATCH], Size); - } - - void AddBusyReg(unsigned Reg) { - if (Reg != X86::NoRegister) - BusyRegs.push_back(convReg(Reg, 64)); - } - - void AddBusyRegs(const X86Operand &Op) { - AddBusyReg(Op.getMemBaseReg()); - AddBusyReg(Op.getMemIndexReg()); - } - - unsigned ChooseFrameReg(unsigned Size) const { - static const MCPhysReg Candidates[] = { X86::RBP, X86::RAX, X86::RBX, - X86::RCX, X86::RDX, X86::RDI, - X86::RSI }; - for (unsigned Reg : Candidates) { - if (!std::count(BusyRegs.begin(), BusyRegs.end(), Reg)) - return convReg(Reg, Size); - } - return X86::NoRegister; - } - - private: - unsigned convReg(unsigned Reg, unsigned Size) const { - return Reg == X86::NoRegister ? Reg : getX86SubSuperRegister(Reg, Size); - } - - std::vector BusyRegs; - }; - - X86AddressSanitizer(const MCSubtargetInfo *&STI) - : X86AsmInstrumentation(STI), RepPrefix(false), OrigSPOffset(0) {} - - ~X86AddressSanitizer() override = default; - - // X86AsmInstrumentation implementation: - void InstrumentAndEmitInstruction(const MCInst &Inst, OperandVector &Operands, - MCContext &Ctx, const MCInstrInfo &MII, - MCStreamer &Out) override { - InstrumentMOVS(Inst, Operands, Ctx, MII, Out); - if (RepPrefix) - EmitInstruction(Out, MCInstBuilder(X86::REP_PREFIX)); - - InstrumentMOV(Inst, Operands, Ctx, MII, Out); - - RepPrefix = (Inst.getOpcode() == X86::REP_PREFIX); - if (!RepPrefix) - EmitInstruction(Out, Inst); - } - - // Adjusts up stack and saves all registers used in instrumentation. - virtual void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) = 0; - - // Restores all registers used in instrumentation and adjusts stack. - virtual void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) = 0; - - virtual void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, - bool IsWrite, - const RegisterContext &RegCtx, - MCContext &Ctx, MCStreamer &Out) = 0; - virtual void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, - bool IsWrite, - const RegisterContext &RegCtx, - MCContext &Ctx, MCStreamer &Out) = 0; - - virtual void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, - MCStreamer &Out) = 0; - - void InstrumentMemOperand(X86Operand &Op, unsigned AccessSize, bool IsWrite, - const RegisterContext &RegCtx, MCContext &Ctx, - MCStreamer &Out); - void InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, unsigned CntReg, - unsigned AccessSize, MCContext &Ctx, MCStreamer &Out); - - void InstrumentMOVS(const MCInst &Inst, OperandVector &Operands, - MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); - void InstrumentMOV(const MCInst &Inst, OperandVector &Operands, - MCContext &Ctx, const MCInstrInfo &MII, MCStreamer &Out); - -protected: - void EmitLabel(MCStreamer &Out, MCSymbol *Label) { Out.EmitLabel(Label); } - - void EmitLEA(X86Operand &Op, unsigned Size, unsigned Reg, MCStreamer &Out) { - assert(Size == 32 || Size == 64); - MCInst Inst; - Inst.setOpcode(Size == 32 ? X86::LEA32r : X86::LEA64r); - Inst.addOperand(MCOperand::createReg(getX86SubSuperRegister(Reg, Size))); - Op.addMemOperands(Inst, 5); - EmitInstruction(Out, Inst); - } - - void ComputeMemOperandAddress(X86Operand &Op, unsigned Size, - unsigned Reg, MCContext &Ctx, MCStreamer &Out); - - // Creates new memory operand with Displacement added to an original - // displacement. Residue will contain a residue which could happen when the - // total displacement exceeds 32-bit limitation. - std::unique_ptr AddDisplacement(X86Operand &Op, - int64_t Displacement, - MCContext &Ctx, int64_t *Residue); - - bool is64BitMode() const { - return STI->getFeatureBits()[X86::Mode64Bit]; - } - - bool is32BitMode() const { - return STI->getFeatureBits()[X86::Mode32Bit]; - } - - bool is16BitMode() const { - return STI->getFeatureBits()[X86::Mode16Bit]; - } - - unsigned getPointerWidth() { - if (is16BitMode()) return 16; - if (is32BitMode()) return 32; - if (is64BitMode()) return 64; - llvm_unreachable("invalid mode"); - } - - // True when previous instruction was actually REP prefix. - bool RepPrefix; - - // Offset from the original SP register. - int64_t OrigSPOffset; -}; - -void X86AddressSanitizer::InstrumentMemOperand( - X86Operand &Op, unsigned AccessSize, bool IsWrite, - const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { - assert(Op.isMem() && "Op should be a memory operand."); - assert((AccessSize & (AccessSize - 1)) == 0 && AccessSize <= 16 && - "AccessSize should be a power of two, less or equal than 16."); - // FIXME: take into account load/store alignment. - if (IsSmallMemAccess(AccessSize)) - InstrumentMemOperandSmall(Op, AccessSize, IsWrite, RegCtx, Ctx, Out); - else - InstrumentMemOperandLarge(Op, AccessSize, IsWrite, RegCtx, Ctx, Out); -} - -void X86AddressSanitizer::InstrumentMOVSBase(unsigned DstReg, unsigned SrcReg, - unsigned CntReg, - unsigned AccessSize, - MCContext &Ctx, MCStreamer &Out) { - // FIXME: check whole ranges [DstReg .. DstReg + AccessSize * (CntReg - 1)] - // and [SrcReg .. SrcReg + AccessSize * (CntReg - 1)]. - RegisterContext RegCtx(X86::RDX /* AddressReg */, X86::RAX /* ShadowReg */, - IsSmallMemAccess(AccessSize) - ? X86::RBX - : X86::NoRegister /* ScratchReg */); - RegCtx.AddBusyReg(DstReg); - RegCtx.AddBusyReg(SrcReg); - RegCtx.AddBusyReg(CntReg); - - InstrumentMemOperandPrologue(RegCtx, Ctx, Out); - - // Test (%SrcReg) - { - const MCExpr *Disp = MCConstantExpr::create(0, Ctx); - std::unique_ptr Op(X86Operand::CreateMem( - getPointerWidth(), 0, Disp, SrcReg, 0, AccessSize, SMLoc(), SMLoc())); - InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, - Out); - } - - // Test -1(%SrcReg, %CntReg, AccessSize) - { - const MCExpr *Disp = MCConstantExpr::create(-1, Ctx); - std::unique_ptr Op(X86Operand::CreateMem( - getPointerWidth(), 0, Disp, SrcReg, CntReg, AccessSize, SMLoc(), - SMLoc())); - InstrumentMemOperand(*Op, AccessSize, false /* IsWrite */, RegCtx, Ctx, - Out); - } - - // Test (%DstReg) - { - const MCExpr *Disp = MCConstantExpr::create(0, Ctx); - std::unique_ptr Op(X86Operand::CreateMem( - getPointerWidth(), 0, Disp, DstReg, 0, AccessSize, SMLoc(), SMLoc())); - InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); - } - - // Test -1(%DstReg, %CntReg, AccessSize) - { - const MCExpr *Disp = MCConstantExpr::create(-1, Ctx); - std::unique_ptr Op(X86Operand::CreateMem( - getPointerWidth(), 0, Disp, DstReg, CntReg, AccessSize, SMLoc(), - SMLoc())); - InstrumentMemOperand(*Op, AccessSize, true /* IsWrite */, RegCtx, Ctx, Out); - } - - InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); -} - -void X86AddressSanitizer::InstrumentMOVS(const MCInst &Inst, - OperandVector &Operands, - MCContext &Ctx, const MCInstrInfo &MII, - MCStreamer &Out) { - // Access size in bytes. - unsigned AccessSize = 0; - - switch (Inst.getOpcode()) { - case X86::MOVSB: - AccessSize = 1; - break; - case X86::MOVSW: - AccessSize = 2; - break; - case X86::MOVSL: - AccessSize = 4; - break; - case X86::MOVSQ: - AccessSize = 8; - break; - default: - return; - } - - InstrumentMOVSImpl(AccessSize, Ctx, Out); -} - -void X86AddressSanitizer::InstrumentMOV(const MCInst &Inst, - OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, - MCStreamer &Out) { - // Access size in bytes. - unsigned AccessSize = 0; - - switch (Inst.getOpcode()) { - case X86::MOV8mi: - case X86::MOV8mr: - case X86::MOV8rm: - AccessSize = 1; - break; - case X86::MOV16mi: - case X86::MOV16mr: - case X86::MOV16rm: - AccessSize = 2; - break; - case X86::MOV32mi: - case X86::MOV32mr: - case X86::MOV32rm: - AccessSize = 4; - break; - case X86::MOV64mi32: - case X86::MOV64mr: - case X86::MOV64rm: - AccessSize = 8; - break; - case X86::MOVAPDmr: - case X86::MOVAPSmr: - case X86::MOVAPDrm: - case X86::MOVAPSrm: - AccessSize = 16; - break; - default: - return; - } - - const bool IsWrite = MII.get(Inst.getOpcode()).mayStore(); - - for (unsigned Ix = 0; Ix < Operands.size(); ++Ix) { - assert(Operands[Ix]); - MCParsedAsmOperand &Op = *Operands[Ix]; - if (Op.isMem()) { - X86Operand &MemOp = static_cast(Op); - RegisterContext RegCtx( - X86::RDI /* AddressReg */, X86::RAX /* ShadowReg */, - IsSmallMemAccess(AccessSize) ? X86::RCX - : X86::NoRegister /* ScratchReg */); - RegCtx.AddBusyRegs(MemOp); - InstrumentMemOperandPrologue(RegCtx, Ctx, Out); - InstrumentMemOperand(MemOp, AccessSize, IsWrite, RegCtx, Ctx, Out); - InstrumentMemOperandEpilogue(RegCtx, Ctx, Out); - } - } -} - -void X86AddressSanitizer::ComputeMemOperandAddress(X86Operand &Op, - unsigned Size, - unsigned Reg, MCContext &Ctx, - MCStreamer &Out) { - int64_t Displacement = 0; - if (IsStackReg(Op.getMemBaseReg())) - Displacement -= OrigSPOffset; - if (IsStackReg(Op.getMemIndexReg())) - Displacement -= OrigSPOffset * Op.getMemScale(); - - assert(Displacement >= 0); - - // Emit Op as is. - if (Displacement == 0) { - EmitLEA(Op, Size, Reg, Out); - return; - } - - int64_t Residue; - std::unique_ptr NewOp = - AddDisplacement(Op, Displacement, Ctx, &Residue); - EmitLEA(*NewOp, Size, Reg, Out); - - while (Residue != 0) { - const MCConstantExpr *Disp = - MCConstantExpr::create(ApplyDisplacementBounds(Residue), Ctx); - std::unique_ptr DispOp = - X86Operand::CreateMem(getPointerWidth(), 0, Disp, Reg, 0, 1, SMLoc(), - SMLoc()); - EmitLEA(*DispOp, Size, Reg, Out); - Residue -= Disp->getValue(); - } -} - -std::unique_ptr -X86AddressSanitizer::AddDisplacement(X86Operand &Op, int64_t Displacement, - MCContext &Ctx, int64_t *Residue) { - assert(Displacement >= 0); - - if (Displacement == 0 || - (Op.getMemDisp() && Op.getMemDisp()->getKind() != MCExpr::Constant)) { - *Residue = Displacement; - return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), - Op.getMemDisp(), Op.getMemBaseReg(), - Op.getMemIndexReg(), Op.getMemScale(), - SMLoc(), SMLoc()); - } - - int64_t OrigDisplacement = - static_cast(Op.getMemDisp())->getValue(); - CheckDisplacementBounds(OrigDisplacement); - Displacement += OrigDisplacement; - - int64_t NewDisplacement = ApplyDisplacementBounds(Displacement); - CheckDisplacementBounds(NewDisplacement); - - *Residue = Displacement - NewDisplacement; - const MCExpr *Disp = MCConstantExpr::create(NewDisplacement, Ctx); - return X86Operand::CreateMem(Op.getMemModeSize(), Op.getMemSegReg(), Disp, - Op.getMemBaseReg(), Op.getMemIndexReg(), - Op.getMemScale(), SMLoc(), SMLoc()); -} - -class X86AddressSanitizer32 : public X86AddressSanitizer { -public: - static const long kShadowOffset = 0x20000000; - - X86AddressSanitizer32(const MCSubtargetInfo *&STI) - : X86AddressSanitizer(STI) {} - - ~X86AddressSanitizer32() override = default; - - unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { - unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); - if (FrameReg == X86::NoRegister) - return FrameReg; - return getX86SubSuperRegister(FrameReg, 32); - } - - void SpillReg(MCStreamer &Out, unsigned Reg) { - EmitInstruction(Out, MCInstBuilder(X86::PUSH32r).addReg(Reg)); - OrigSPOffset -= 4; - } - - void RestoreReg(MCStreamer &Out, unsigned Reg) { - EmitInstruction(Out, MCInstBuilder(X86::POP32r).addReg(Reg)); - OrigSPOffset += 4; - } - - void StoreFlags(MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::PUSHF32)); - OrigSPOffset -= 4; - } - - void RestoreFlags(MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::POPF32)); - OrigSPOffset += 4; - } - - void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override { - unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32); - assert(LocalFrameReg != X86::NoRegister); - - const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); - unsigned FrameReg = GetFrameReg(Ctx, Out); - if (MRI && FrameReg != X86::NoRegister) { - SpillReg(Out, LocalFrameReg); - if (FrameReg == X86::ESP) { - Out.EmitCFIAdjustCfaOffset(4 /* byte size of the LocalFrameReg */); - Out.EmitCFIRelOffset( - MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); - } - EmitInstruction( - Out, - MCInstBuilder(X86::MOV32rr).addReg(LocalFrameReg).addReg(FrameReg)); - Out.EmitCFIRememberState(); - Out.EmitCFIDefCfaRegister( - MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); - } - - SpillReg(Out, RegCtx.AddressReg(32)); - SpillReg(Out, RegCtx.ShadowReg(32)); - if (RegCtx.ScratchReg(32) != X86::NoRegister) - SpillReg(Out, RegCtx.ScratchReg(32)); - StoreFlags(Out); - } - - void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override { - unsigned LocalFrameReg = RegCtx.ChooseFrameReg(32); - assert(LocalFrameReg != X86::NoRegister); - - RestoreFlags(Out); - if (RegCtx.ScratchReg(32) != X86::NoRegister) - RestoreReg(Out, RegCtx.ScratchReg(32)); - RestoreReg(Out, RegCtx.ShadowReg(32)); - RestoreReg(Out, RegCtx.AddressReg(32)); - - unsigned FrameReg = GetFrameReg(Ctx, Out); - if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { - RestoreReg(Out, LocalFrameReg); - Out.EmitCFIRestoreState(); - if (FrameReg == X86::ESP) - Out.EmitCFIAdjustCfaOffset(-4 /* byte size of the LocalFrameReg */); - } - } - - void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, - bool IsWrite, - const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override; - void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, - bool IsWrite, - const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override; - void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, - MCStreamer &Out) override; - -private: - void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out, const RegisterContext &RegCtx) { - EmitInstruction(Out, MCInstBuilder(X86::CLD)); - EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); - - EmitInstruction(Out, MCInstBuilder(X86::AND32ri8) - .addReg(X86::ESP) - .addReg(X86::ESP) - .addImm(-16)); - EmitInstruction( - Out, MCInstBuilder(X86::PUSH32r).addReg(RegCtx.AddressReg(32))); - - MCSymbol *FnSym = Ctx.getOrCreateSymbol(Twine("__asan_report_") + - (IsWrite ? "store" : "load") + - Twine(AccessSize)); - const MCSymbolRefExpr *FnExpr = - MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::CALLpcrel32).addExpr(FnExpr)); - } -}; - -void X86AddressSanitizer32::InstrumentMemOperandSmall( - X86Operand &Op, unsigned AccessSize, bool IsWrite, - const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { - unsigned AddressRegI32 = RegCtx.AddressReg(32); - unsigned ShadowRegI32 = RegCtx.ShadowReg(32); - unsigned ShadowRegI8 = RegCtx.ShadowReg(8); - - assert(RegCtx.ScratchReg(32) != X86::NoRegister); - unsigned ScratchRegI32 = RegCtx.ScratchReg(32); - - ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out); - - EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( - AddressRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) - .addReg(ShadowRegI32) - .addReg(ShadowRegI32) - .addImm(3)); - - { - MCInst Inst; - Inst.setOpcode(X86::MOV8rm); - Inst.addOperand(MCOperand::createReg(ShadowRegI8)); - const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, - SMLoc(), SMLoc())); - Op->addMemOperands(Inst, 5); - EmitInstruction(Out, Inst); - } - - EmitInstruction( - Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); - MCSymbol *DoneSym = Ctx.createTempSymbol(); - const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); - - EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( - AddressRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::AND32ri) - .addReg(ScratchRegI32) - .addReg(ScratchRegI32) - .addImm(7)); - - switch (AccessSize) { - default: llvm_unreachable("Incorrect access size"); - case 1: - break; - case 2: { - const MCExpr *Disp = MCConstantExpr::create(1, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, - SMLoc(), SMLoc())); - EmitLEA(*Op, 32, ScratchRegI32, Out); - break; - } - case 4: - EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) - .addReg(ScratchRegI32) - .addReg(ScratchRegI32) - .addImm(3)); - break; - } - - EmitInstruction( - Out, - MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); - EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( - ShadowRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); - - EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); - EmitLabel(Out, DoneSym); -} - -void X86AddressSanitizer32::InstrumentMemOperandLarge( - X86Operand &Op, unsigned AccessSize, bool IsWrite, - const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { - unsigned AddressRegI32 = RegCtx.AddressReg(32); - unsigned ShadowRegI32 = RegCtx.ShadowReg(32); - - ComputeMemOperandAddress(Op, 32, AddressRegI32, Ctx, Out); - - EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ShadowRegI32).addReg( - AddressRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::SHR32ri) - .addReg(ShadowRegI32) - .addReg(ShadowRegI32) - .addImm(3)); - { - MCInst Inst; - switch (AccessSize) { - default: llvm_unreachable("Incorrect access size"); - case 8: - Inst.setOpcode(X86::CMP8mi); - break; - case 16: - Inst.setOpcode(X86::CMP16mi); - break; - } - const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI32, 0, 1, - SMLoc(), SMLoc())); - Op->addMemOperands(Inst, 5); - Inst.addOperand(MCOperand::createImm(0)); - EmitInstruction(Out, Inst); - } - MCSymbol *DoneSym = Ctx.createTempSymbol(); - const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); - - EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); - EmitLabel(Out, DoneSym); -} - -void X86AddressSanitizer32::InstrumentMOVSImpl(unsigned AccessSize, - MCContext &Ctx, - MCStreamer &Out) { - StoreFlags(Out); - - // No need to test when ECX is equals to zero. - MCSymbol *DoneSym = Ctx.createTempSymbol(); - const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); - EmitInstruction( - Out, MCInstBuilder(X86::TEST32rr).addReg(X86::ECX).addReg(X86::ECX)); - EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); - - // Instrument first and last elements in src and dst range. - InstrumentMOVSBase(X86::EDI /* DstReg */, X86::ESI /* SrcReg */, - X86::ECX /* CntReg */, AccessSize, Ctx, Out); - - EmitLabel(Out, DoneSym); - RestoreFlags(Out); -} - -class X86AddressSanitizer64 : public X86AddressSanitizer { -public: - static const long kShadowOffset = 0x7fff8000; - - X86AddressSanitizer64(const MCSubtargetInfo *&STI) - : X86AddressSanitizer(STI) {} - - ~X86AddressSanitizer64() override = default; - - unsigned GetFrameReg(const MCContext &Ctx, MCStreamer &Out) { - unsigned FrameReg = GetFrameRegGeneric(Ctx, Out); - if (FrameReg == X86::NoRegister) - return FrameReg; - return getX86SubSuperRegister(FrameReg, 64); - } - - void SpillReg(MCStreamer &Out, unsigned Reg) { - EmitInstruction(Out, MCInstBuilder(X86::PUSH64r).addReg(Reg)); - OrigSPOffset -= 8; - } - - void RestoreReg(MCStreamer &Out, unsigned Reg) { - EmitInstruction(Out, MCInstBuilder(X86::POP64r).addReg(Reg)); - OrigSPOffset += 8; - } - - void StoreFlags(MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::PUSHF64)); - OrigSPOffset -= 8; - } - - void RestoreFlags(MCStreamer &Out) { - EmitInstruction(Out, MCInstBuilder(X86::POPF64)); - OrigSPOffset += 8; - } - - void InstrumentMemOperandPrologue(const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override { - unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64); - assert(LocalFrameReg != X86::NoRegister); - - const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); - unsigned FrameReg = GetFrameReg(Ctx, Out); - if (MRI && FrameReg != X86::NoRegister) { - SpillReg(Out, X86::RBP); - if (FrameReg == X86::RSP) { - Out.EmitCFIAdjustCfaOffset(8 /* byte size of the LocalFrameReg */); - Out.EmitCFIRelOffset( - MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */), 0); - } - EmitInstruction( - Out, - MCInstBuilder(X86::MOV64rr).addReg(LocalFrameReg).addReg(FrameReg)); - Out.EmitCFIRememberState(); - Out.EmitCFIDefCfaRegister( - MRI->getDwarfRegNum(LocalFrameReg, true /* IsEH */)); - } - - EmitAdjustRSP(Ctx, Out, -128); - SpillReg(Out, RegCtx.ShadowReg(64)); - SpillReg(Out, RegCtx.AddressReg(64)); - if (RegCtx.ScratchReg(64) != X86::NoRegister) - SpillReg(Out, RegCtx.ScratchReg(64)); - StoreFlags(Out); - } - - void InstrumentMemOperandEpilogue(const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override { - unsigned LocalFrameReg = RegCtx.ChooseFrameReg(64); - assert(LocalFrameReg != X86::NoRegister); - - RestoreFlags(Out); - if (RegCtx.ScratchReg(64) != X86::NoRegister) - RestoreReg(Out, RegCtx.ScratchReg(64)); - RestoreReg(Out, RegCtx.AddressReg(64)); - RestoreReg(Out, RegCtx.ShadowReg(64)); - EmitAdjustRSP(Ctx, Out, 128); - - unsigned FrameReg = GetFrameReg(Ctx, Out); - if (Ctx.getRegisterInfo() && FrameReg != X86::NoRegister) { - RestoreReg(Out, LocalFrameReg); - Out.EmitCFIRestoreState(); - if (FrameReg == X86::RSP) - Out.EmitCFIAdjustCfaOffset(-8 /* byte size of the LocalFrameReg */); - } - } - - void InstrumentMemOperandSmall(X86Operand &Op, unsigned AccessSize, - bool IsWrite, - const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override; - void InstrumentMemOperandLarge(X86Operand &Op, unsigned AccessSize, - bool IsWrite, - const RegisterContext &RegCtx, - MCContext &Ctx, - MCStreamer &Out) override; - void InstrumentMOVSImpl(unsigned AccessSize, MCContext &Ctx, - MCStreamer &Out) override; - -private: - void EmitAdjustRSP(MCContext &Ctx, MCStreamer &Out, long Offset) { - const MCExpr *Disp = MCConstantExpr::create(Offset, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, X86::RSP, 0, 1, - SMLoc(), SMLoc())); - EmitLEA(*Op, 64, X86::RSP, Out); - OrigSPOffset += Offset; - } - - void EmitCallAsanReport(unsigned AccessSize, bool IsWrite, MCContext &Ctx, - MCStreamer &Out, const RegisterContext &RegCtx) { - EmitInstruction(Out, MCInstBuilder(X86::CLD)); - EmitInstruction(Out, MCInstBuilder(X86::MMX_EMMS)); - - EmitInstruction(Out, MCInstBuilder(X86::AND64ri8) - .addReg(X86::RSP) - .addReg(X86::RSP) - .addImm(-16)); - - if (RegCtx.AddressReg(64) != X86::RDI) { - EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(X86::RDI).addReg( - RegCtx.AddressReg(64))); - } - MCSymbol *FnSym = Ctx.getOrCreateSymbol(Twine("__asan_report_") + - (IsWrite ? "store" : "load") + - Twine(AccessSize)); - const MCSymbolRefExpr *FnExpr = - MCSymbolRefExpr::create(FnSym, MCSymbolRefExpr::VK_PLT, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::CALL64pcrel32).addExpr(FnExpr)); - } -}; - -} // end anonymous namespace - -void X86AddressSanitizer64::InstrumentMemOperandSmall( - X86Operand &Op, unsigned AccessSize, bool IsWrite, - const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { - unsigned AddressRegI64 = RegCtx.AddressReg(64); - unsigned AddressRegI32 = RegCtx.AddressReg(32); - unsigned ShadowRegI64 = RegCtx.ShadowReg(64); - unsigned ShadowRegI32 = RegCtx.ShadowReg(32); - unsigned ShadowRegI8 = RegCtx.ShadowReg(8); - - assert(RegCtx.ScratchReg(32) != X86::NoRegister); - unsigned ScratchRegI32 = RegCtx.ScratchReg(32); - - ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out); - - EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( - AddressRegI64)); - EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) - .addReg(ShadowRegI64) - .addReg(ShadowRegI64) - .addImm(3)); - { - MCInst Inst; - Inst.setOpcode(X86::MOV8rm); - Inst.addOperand(MCOperand::createReg(ShadowRegI8)); - const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, - SMLoc(), SMLoc())); - Op->addMemOperands(Inst, 5); - EmitInstruction(Out, Inst); - } - - EmitInstruction( - Out, MCInstBuilder(X86::TEST8rr).addReg(ShadowRegI8).addReg(ShadowRegI8)); - MCSymbol *DoneSym = Ctx.createTempSymbol(); - const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); - - EmitInstruction(Out, MCInstBuilder(X86::MOV32rr).addReg(ScratchRegI32).addReg( - AddressRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::AND32ri) - .addReg(ScratchRegI32) - .addReg(ScratchRegI32) - .addImm(7)); - - switch (AccessSize) { - default: llvm_unreachable("Incorrect access size"); - case 1: - break; - case 2: { - const MCExpr *Disp = MCConstantExpr::create(1, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, ScratchRegI32, 0, 1, - SMLoc(), SMLoc())); - EmitLEA(*Op, 32, ScratchRegI32, Out); - break; - } - case 4: - EmitInstruction(Out, MCInstBuilder(X86::ADD32ri8) - .addReg(ScratchRegI32) - .addReg(ScratchRegI32) - .addImm(3)); - break; - } - - EmitInstruction( - Out, - MCInstBuilder(X86::MOVSX32rr8).addReg(ShadowRegI32).addReg(ShadowRegI8)); - EmitInstruction(Out, MCInstBuilder(X86::CMP32rr).addReg(ScratchRegI32).addReg( - ShadowRegI32)); - EmitInstruction(Out, MCInstBuilder(X86::JL_1).addExpr(DoneExpr)); - - EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); - EmitLabel(Out, DoneSym); -} - -void X86AddressSanitizer64::InstrumentMemOperandLarge( - X86Operand &Op, unsigned AccessSize, bool IsWrite, - const RegisterContext &RegCtx, MCContext &Ctx, MCStreamer &Out) { - unsigned AddressRegI64 = RegCtx.AddressReg(64); - unsigned ShadowRegI64 = RegCtx.ShadowReg(64); - - ComputeMemOperandAddress(Op, 64, AddressRegI64, Ctx, Out); - - EmitInstruction(Out, MCInstBuilder(X86::MOV64rr).addReg(ShadowRegI64).addReg( - AddressRegI64)); - EmitInstruction(Out, MCInstBuilder(X86::SHR64ri) - .addReg(ShadowRegI64) - .addReg(ShadowRegI64) - .addImm(3)); - { - MCInst Inst; - switch (AccessSize) { - default: llvm_unreachable("Incorrect access size"); - case 8: - Inst.setOpcode(X86::CMP8mi); - break; - case 16: - Inst.setOpcode(X86::CMP16mi); - break; - } - const MCExpr *Disp = MCConstantExpr::create(kShadowOffset, Ctx); - std::unique_ptr Op( - X86Operand::CreateMem(getPointerWidth(), 0, Disp, ShadowRegI64, 0, 1, - SMLoc(), SMLoc())); - Op->addMemOperands(Inst, 5); - Inst.addOperand(MCOperand::createImm(0)); - EmitInstruction(Out, Inst); - } - - MCSymbol *DoneSym = Ctx.createTempSymbol(); - const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); - EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); - - EmitCallAsanReport(AccessSize, IsWrite, Ctx, Out, RegCtx); - EmitLabel(Out, DoneSym); -} - -void X86AddressSanitizer64::InstrumentMOVSImpl(unsigned AccessSize, - MCContext &Ctx, - MCStreamer &Out) { - StoreFlags(Out); - - // No need to test when RCX is equals to zero. - MCSymbol *DoneSym = Ctx.createTempSymbol(); - const MCExpr *DoneExpr = MCSymbolRefExpr::create(DoneSym, Ctx); - EmitInstruction( - Out, MCInstBuilder(X86::TEST64rr).addReg(X86::RCX).addReg(X86::RCX)); - EmitInstruction(Out, MCInstBuilder(X86::JE_1).addExpr(DoneExpr)); - - // Instrument first and last elements in src and dst range. - InstrumentMOVSBase(X86::RDI /* DstReg */, X86::RSI /* SrcReg */, - X86::RCX /* CntReg */, AccessSize, Ctx, Out); - - EmitLabel(Out, DoneSym); - RestoreFlags(Out); -} - -X86AsmInstrumentation::X86AsmInstrumentation(const MCSubtargetInfo *&STI) - : STI(STI) {} - -X86AsmInstrumentation::~X86AsmInstrumentation() = default; - -void X86AsmInstrumentation::InstrumentAndEmitInstruction( - const MCInst &Inst, OperandVector &Operands, MCContext &Ctx, - const MCInstrInfo &MII, MCStreamer &Out) { - EmitInstruction(Out, Inst); -} - -void X86AsmInstrumentation::EmitInstruction(MCStreamer &Out, - const MCInst &Inst) { - Out.EmitInstruction(Inst, *STI); -} - -unsigned X86AsmInstrumentation::GetFrameRegGeneric(const MCContext &Ctx, - MCStreamer &Out) { - if (!Out.getNumFrameInfos()) // No active dwarf frame - return X86::NoRegister; - const MCDwarfFrameInfo &Frame = Out.getDwarfFrameInfos().back(); - if (Frame.End) // Active dwarf frame is closed - return X86::NoRegister; - const MCRegisterInfo *MRI = Ctx.getRegisterInfo(); - if (!MRI) // No register info - return X86::NoRegister; - - if (InitialFrameReg) { - // FrameReg is set explicitly, we're instrumenting a MachineFunction. - return InitialFrameReg; - } - - return MRI->getLLVMRegNum(Frame.CurrentCfaRegister, true /* IsEH */); -} - -X86AsmInstrumentation * -llvm::CreateX86AsmInstrumentation(const MCTargetOptions &MCOptions, - const MCContext &Ctx, - const MCSubtargetInfo *&STI) { - Triple T(STI->getTargetTriple()); - const bool hasCompilerRTSupport = T.isOSLinux(); - if (ClAsanInstrumentAssembly && hasCompilerRTSupport && - MCOptions.SanitizeAddress) { - if (STI->getFeatureBits()[X86::Mode32Bit] != 0) - return new X86AddressSanitizer32(STI); - if (STI->getFeatureBits()[X86::Mode64Bit] != 0) - return new X86AddressSanitizer64(STI); - } - return new X86AsmInstrumentation(STI); -} Index: llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ llvm/trunk/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -10,7 +10,6 @@ #include "MCTargetDesc/X86BaseInfo.h" #include "MCTargetDesc/X86MCExpr.h" #include "MCTargetDesc/X86TargetStreamer.h" -#include "X86AsmInstrumentation.h" #include "X86AsmParserCommon.h" #include "X86Operand.h" #include "llvm/ADT/STLExtras.h" @@ -70,7 +69,6 @@ class X86AsmParser : public MCTargetAsmParser { ParseInstructionInfo *InstInfo; - std::unique_ptr Instrumentation; bool Code16GCC; private: @@ -951,14 +949,10 @@ // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); - Instrumentation.reset( - CreateX86AsmInstrumentation(Options, Parser.getContext(), STI)); } bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; - void SetFrameRegister(unsigned RegNo) override; - bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override; bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, @@ -1193,10 +1187,6 @@ return false; } -void X86AsmParser::SetFrameRegister(unsigned RegNo) { - Instrumentation->SetInitialFrameRegister(RegNo); -} - std::unique_ptr X86AsmParser::DefaultMemSIOperand(SMLoc Loc) { bool Parse32 = is32BitMode() || Code16GCC; unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI); @@ -2866,8 +2856,7 @@ void X86AsmParser::EmitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out) { - Instrumentation->InstrumentAndEmitInstruction( - Inst, Operands, getContext(), MII, Out); + Out.EmitInstruction(Inst, getSTI()); } bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_attr.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_attr.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_attr.ll @@ -1,20 +0,0 @@ -; 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: mov_no_attr -; CHECK-NOT: callq __asan_report_load8@PLT -; CHECK-NOT: callq __asan_report_store8@PLT -define void @mov_no_attr(i64* %dst, i64* %src) { - tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src) - ret void -} - -; CHECK-LABEL: mov_sanitize -; CHECK: callq __asan_report_load8@PLT -; CHECK: callq __asan_report_store8@PLT -define void @mov_sanitize(i64* %dst, i64* %src) sanitize_address { - tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src) - ret void -} Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll @@ -1,54 +0,0 @@ -; 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 -} - -; CHECK-LABEL: mov8b_rsp_no_cfi -; CHECK-NOT: .cfi{{[a-z_]+}} -define void @mov8b_rsp_no_cfi(i64* %dst, i64* %src) #2 { -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" } -attributes #2 = { nounwind sanitize_address "no-frame-pointer-elim"="false" } Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_cfi.s =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_cfi.s +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_cfi.s @@ -1,52 +0,0 @@ -# The test verifies that correct DWARF directives are emitted when -# assembly files are instrumented. - -# RUN: llvm-mc %s -triple=i386-unknown-linux-gnu -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s - -# CHECK-LABEL: load4b_cfa_rbp -# CHECK: pushl %ebx -# CHECK-NOT: .cfi_adjust_cfa_offset 8 -# CHECK: movl %ebp, %ebx -# CHECK: .cfi_remember_state -# CHECK: .cfi_def_cfa_register %ebx -# CHECK: popl %ebx -# CHECK: .cfi_restore_state -# CHECK-NOT: .cfi_adjust_cfa_offset -8 -# CHECK: retl - - .text - .globl load4b_cfa_rbp - .type load4b_cfa_rbp,@function -swap_cfa_rbp: # @swap_cfa_rbp - .cfi_startproc - pushl %ebp - .cfi_def_cfa_offset 8 - .cfi_offset %ebp, -8 - movl %esp, %ebp - .cfi_def_cfa_register %ebp - movl 8(%ebp), %eax - popl %ebp - retl - .cfi_endproc - -# CHECK-LABEL: load4b_cfa_rsp -# CHECK: pushl %ebx -# CHECK: .cfi_adjust_cfa_offset 4 -# CHECK: movl %esp, %ebx -# CHECK: .cfi_remember_state -# CHECK: .cfi_def_cfa_register %ebx -# CHECK: popl %ebx -# CHECK: .cfi_restore_state -# CHECK: retl - - .globl load4b_cfa_rsp - .type load4b_cfa_rsp,@function -swap_cfa_rsp: # @swap_cfa_rsp - .cfi_startproc - pushl %ebp - .cfi_offset %ebp, 0 - movl %esp, %ebp - movl 8(%ebp), %eax - popl %ebp - retl - .cfi_endproc Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_mov.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_mov.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_mov.ll @@ -1,152 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2 -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s - -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -; CHECK-LABEL: mov1b -; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rax -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: pushq %rcx -; CHECK-NEXT: pushfq -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: shrq $3, %rax -; CHECK-NEXT: movb 2147450880(%rax), %al -; CHECK-NEXT: testb %al, %al -; CHECK-NEXT: je [[A:.*]] -; CHECK-NEXT: movl %edi, %ecx -; CHECK-NEXT: andl $7, %ecx -; CHECK-NEXT: movsbl %al, %eax -; CHECK-NEXT: cmpl %eax, %ecx -; CHECK-NEXT: jl {{.*}} -; CHECK-NEXT: cld -; CHECK-NEXT: emms -; CHECK-NEXT: andq $-16, %rsp -; CHECK-NEXT: callq __asan_report_load1@PLT -; CHECK-NEXT: [[A]]: -; CHECK-NEXT: popfq -; CHECK-NEXT: popq %rcx -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: popq %rax -; CHECK-NEXT: leaq 128(%rsp), %rsp - -; CHECK: leaq -128(%rsp), %rsp -; CHECK: callq __asan_report_store1@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: movb {{.*}}, {{.*}} -define void @mov1b(i8* %dst, i8* %src) #0 { -entry: - tail call void asm sideeffect "movb ($1), %al \0A\09movb %al, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i8* %dst, i8* %src) #1, !srcloc !0 - ret void -} - -; CHECK-LABEL: mov2b -; CHECK: leaq -128(%rsp), %rsp -; CHECK: leal 1(%ecx), %ecx -; CHECK: callq __asan_report_load2@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: leaq -128(%rsp), %rsp -; CHECK: leal 1(%ecx), %ecx -; CHECK: callq __asan_report_store2@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: movw {{.*}}, {{.*}} -define void @mov2b(i16* %dst, i16* %src) #0 { -entry: - tail call void asm sideeffect "movw ($1), %ax \0A\09movw %ax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i16* %dst, i16* %src) #1, !srcloc !1 - ret void -} - -; CHECK-LABEL: mov4b -; CHECK: leaq -128(%rsp), %rsp -; CHECK: addl $3, %ecx -; CHECK: callq __asan_report_load4@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: leaq -128(%rsp), %rsp -; CHECK: addl $3, %ecx -; CHECK: callq __asan_report_store4@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: movl {{.*}}, {{.*}} -define void @mov4b(i32* %dst, i32* %src) #0 { -entry: - tail call void asm sideeffect "movl ($1), %eax \0A\09movl %eax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i32* %dst, i32* %src) #1, !srcloc !2 - ret void -} - -; CHECK-LABEL: mov8b -; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rax -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: pushfq -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: shrq $3, %rax -; CHECK-NEXT: cmpb $0, 2147450880(%rax) -; CHECK-NEXT: je [[A:.*]] -; CHECK-NEXT: cld -; CHECK-NEXT: emms -; CHECK-NEXT: andq $-16, %rsp -; CHECK-NEXT: callq __asan_report_load8@PLT -; CHECK-NEXT: [[A]]: -; CHECK-NEXT: popfq -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: popq %rax -; CHECK-NEXT: leaq 128(%rsp), %rsp - -; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rax -; CHECK-NEXT: pushq %rdi -; CHECK-NEXT: pushfq -; CHECK-NEXT: leaq {{.*}}, %rdi -; CHECK-NEXT: movq %rdi, %rax -; CHECK-NEXT: shrq $3, %rax -; CHECK-NEXT: cmpb $0, 2147450880(%rax) -; CHECK-NEXT: je [[A:.*]] -; CHECK-NEXT: cld -; CHECK-NEXT: emms -; CHECK-NEXT: andq $-16, %rsp -; CHECK-NEXT: callq __asan_report_store8@PLT -; CHECK-NEXT: [[A]]: -; CHECK-NEXT: popfq -; CHECK-NEXT: popq %rdi -; CHECK-NEXT: popq %rax -; CHECK-NEXT: leaq 128(%rsp), %rsp - -; CHECK: movq {{.*}}, {{.*}} -define void @mov8b(i64* %dst, i64* %src) #0 { -entry: - tail call void asm sideeffect "movq ($1), %rax \0A\09movq %rax, ($0) \0A\09", "r,r,~{memory},~{rax},~{dirflag},~{fpsr},~{flags}"(i64* %dst, i64* %src) #1, !srcloc !3 - ret void -} - -; CHECK-LABEL: mov16b -; CHECK: leaq -128(%rsp), %rsp -; CHECK: cmpw $0, 2147450880(%rax) -; CHECK: callq __asan_report_load16@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: leaq -128(%rsp), %rsp -; CHECK: cmpw $0, 2147450880(%rax) -; CHECK: callq __asan_report_store16@PLT -; CHECK: leaq 128(%rsp), %rsp - -; CHECK: movaps {{.*}}, {{.*}} -define void @mov16b(<2 x i64>* %dst, <2 x i64>* %src) #0 { -entry: - tail call void asm sideeffect "movaps ($1), %xmm0 \0A\09movaps %xmm0, ($0) \0A\09", "r,r,~{memory},~{xmm0},~{dirflag},~{fpsr},~{flags}"(<2 x i64>* %dst, <2 x i64>* %src) #1, !srcloc !4 - ret void -} - -attributes #0 = { nounwind uwtable sanitize_address "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } - -!0 = !{i32 98, i32 122, i32 160} -!1 = !{i32 305, i32 329, i32 367} -!2 = !{i32 512, i32 537, i32 576} -!3 = !{i32 721, i32 746, i32 785} -!4 = !{i32 929, i32 957, i32 999} Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_mov.s =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_mov.s +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_mov.s @@ -1,64 +0,0 @@ -# RUN: llvm-mc %s -triple=x86_64-unknown-linux-gnu -mcpu=corei7 -mattr=+sse2 -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s - - .text - .globl mov1b - .align 16, 0x90 - .type mov1b,@function -# CHECK-LABEL: mov1b: -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_load1@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movb (%rsi), %al -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_store1@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movb %al, (%rdi) -mov1b: # @mov1b - .cfi_startproc -# %bb.0: - #APP - movb (%rsi), %al - movb %al, (%rdi) - - #NO_APP - retq -.Ltmp0: - .size mov1b, .Ltmp0-mov1b - .cfi_endproc - - .globl mov16b - .align 16, 0x90 - .type mov16b,@function -# CHECK-LABEL: mov16b: -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_load16@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movaps (%rsi), %xmm0 -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_store16@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movaps %xmm0, (%rdi) -mov16b: # @mov16b - .cfi_startproc -# %bb.0: - #APP - movaps (%rsi), %xmm0 - movaps %xmm0, (%rdi) - - #NO_APP - retq -.Ltmp1: - .size mov16b, .Ltmp1-mov16b - .cfi_endproc - - - .ident "clang version 3.5 " - .section ".note.GNU-stack","",@progbits Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll @@ -1,85 +0,0 @@ -; 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: rep_movs_1b -; CHECK: pushfq -; CHECK-NEXT: testq %rcx, %rcx -; CHECK-NEXT: je [[B:.*]] - -; CHECK: leaq -128(%rsp), %rsp -; CHECK-NEXT: pushq %rax -; CHECK-NEXT: pushq %rdx -; CHECK-NEXT: pushq %rbx -; CHECK-NEXT: pushfq - -; CHECK: leaq (%rsi), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_load1@PLT - -; CHECK: leaq -1(%rsi,%rcx), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_load1@PLT - -; CHECK: leaq (%rdi), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_store1@PLT - -; CHECK: leaq -1(%rdi,%rcx), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_store1@PLT - -; CHECK: popfq -; CHECK-NEXT: popq %rbx -; CHECK-NEXT: popq %rdx -; CHECK-NEXT: popq %rax -; CHECK-NEXT: leaq 128(%rsp), %rsp - -; CHECK: [[B]]: -; CHECK-NEXT: popfq - -; CHECK: rep movsb (%rsi), %es:(%rdi) - -; Function Attrs: nounwind sanitize_address uwtable -define void @rep_movs_1b(i8* %dst, i8* %src, i64 %n) #0 { -entry: - tail call void asm sideeffect "rep movsb \0A\09", "{si},{di},{cx},~{memory},~{dirflag},~{fpsr},~{flags}"(i8* %src, i8* %dst, i64 %n) #1 - ret void -} - -; CHECK-LABEL: rep_movs_8b -; CHECK: pushfq -; CHECK-NEXT: testq %rcx, %rcx -; CHECK-NEXT: je [[Q:.*]] - -; CHECK: leaq (%rsi), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_load8@PLT - -; CHECK: leaq -1(%rsi,%rcx,8), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_load8@PLT - -; CHECK: leaq (%rdi), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_store8@PLT - -; CHECK: leaq -1(%rdi,%rcx,8), %rdx -; CHECK: movq %rdx, %rdi -; CHECK-NEXT: callq __asan_report_store8@PLT - -; CHECK: [[Q]]: -; CHECK-NEXT: popfq - -; CHECK: rep movsq (%rsi), %es:(%rdi) - -; Function Attrs: nounwind sanitize_address uwtable -define void @rep_movs_8b(i64* %dst, i64* %src, i64 %n) #0 { -entry: - tail call void asm sideeffect "rep movsq \0A\09", "{si},{di},{cx},~{memory},~{dirflag},~{fpsr},~{flags}"(i64* %src, i64* %dst, i64 %n) #1 - ret void -} - -attributes #0 = { nounwind sanitize_address uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_rsp_mem_op.s =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_rsp_mem_op.s +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_rsp_mem_op.s @@ -1,45 +0,0 @@ -# The test verifies that memory references through %rsp are correctly -# adjusted after instrumentation. - -# RUN: llvm-mc %s -triple=x86_64-unknown-linux-gnu -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s - -# CHECK-LABEL: rsp_access -# CHECK: leaq -128(%rsp), %rsp -# CHECK: pushq %rax -# CHECK: pushq %rdi -# CHECK: pushfq -# CHECK: leaq 160(%rsp), %rdi -# CHECK: callq __asan_report_load8@PLT -# CHECK: popfq -# CHECK: popq %rdi -# CHECK: popq %rax -# CHECK: leaq 128(%rsp), %rsp -# CHECK: movq 8(%rsp), %rax -# CHECK: retq - - .text - .globl rsp_access - .type rsp_access,@function -rsp_access: - movq 8(%rsp), %rax - retq - -# CHECK-LABEL: rsp_32bit_access -# CHECK: leaq -128(%rsp), %rsp -# CHECK: pushq %rax -# CHECK: pushq %rdi -# CHECK: pushfq -# CHECK: leaq 2147483647(%rsp), %rdi -# CHECK: leaq 145(%rdi), %rdi -# CHECK: callq __asan_report_load8@PLT -# CHECK: popfq -# CHECK: popq %rdi -# CHECK: popq %rax -# CHECK: leaq 128(%rsp), %rsp -# CHECK: movq 2147483640(%rsp), %rax -# CHECK: retq - .globl rsp_32bit_access - .type rsp_32bit_access,@function -rsp_32bit_access: - movq 2147483640(%rsp), %rax - retq Index: llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s =================================================================== --- llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s +++ llvm/trunk/test/Instrumentation/AddressSanitizer/X86/asm_swap_intel.s @@ -1,59 +0,0 @@ -# RUN: llvm-mc %s -x86-asm-syntax=intel -triple=x86_64-unknown-linux-gnu -asm-instrumentation=address -asan-instrument-assembly | FileCheck %s - - .text - .globl swap - .align 16, 0x90 - .type swap,@function -# CHECK-LABEL: swap: -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_load8@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movq (%rcx), %rax -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_load8@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movq (%rdx), %rbx -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_store8@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movq %rbx, (%rcx) -# -# CHECK: leaq -128(%rsp), %rsp -# CHECK: callq __asan_report_store8@PLT -# CHECK: leaq 128(%rsp), %rsp -# -# CHECK: movq %rax, (%rdx) -swap: # @swap - .cfi_startproc -# %bb.0: - push rbx -.Ltmp0: - .cfi_def_cfa_offset 16 -.Ltmp1: - .cfi_offset rbx, -16 - mov rcx, rdi - mov rdx, rsi - #APP - - - mov rax, qword ptr [rcx] - mov rbx, qword ptr [rdx] - mov qword ptr [rcx], rbx - mov qword ptr [rdx], rax - - #NO_APP - pop rbx - ret -.Ltmp2: - .size swap, .Ltmp2-swap - .cfi_endproc - - - .ident "clang version 3.5.0 " - .section ".note.GNU-stack","",@progbits Index: llvm/trunk/utils/gn/secondary/llvm/lib/Target/X86/AsmParser/BUILD.gn =================================================================== --- llvm/trunk/utils/gn/secondary/llvm/lib/Target/X86/AsmParser/BUILD.gn +++ llvm/trunk/utils/gn/secondary/llvm/lib/Target/X86/AsmParser/BUILD.gn @@ -19,7 +19,6 @@ ] include_dirs = [ ".." ] sources = [ - "X86AsmInstrumentation.cpp", "X86AsmParser.cpp", ] }