From 7b7499a7a6aedec190821aa21a28f59eb58f8988 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Fri, 3 Mar 2017 01:08:25 +0000 Subject: [PATCH] LiveDebugValues: Assume calls never clobber SP. A call should never modify the stack pointer, but some backends are not so sure about this and never list SP in the regmask. For the purposes of LiveDebugValues we assume a call never clobbers SP. We already have a similar workaround in DbgValueHistoryCalculator (which we hopefully can retire soon). This fixes the availabilty of local ASANified variables on AArch64. rdar://problem/27757381 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@296847 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/LiveDebugValues.cpp | 6 +- test/DebugInfo/AArch64/asan-stack-vars.ll | 326 ++++++++++++++++++++++ 2 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 test/DebugInfo/AArch64/asan-stack-vars.ll diff --git a/lib/CodeGen/LiveDebugValues.cpp b/lib/CodeGen/LiveDebugValues.cpp index 3e079d6774e..f956974b1aa 100644 --- a/lib/CodeGen/LiveDebugValues.cpp +++ b/lib/CodeGen/LiveDebugValues.cpp @@ -373,8 +373,12 @@ void LiveDebugValues::transferRegisterDef(MachineInstr &MI, unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); SparseBitVector<> KillSet; for (const MachineOperand &MO : MI.operands()) { + // Determine whether the operand is a register def. Assume that call + // instructions never clobber SP, because some backends (e.g., AArch64) + // never list SP in the regmask. if (MO.isReg() && MO.isDef() && MO.getReg() && - TRI->isPhysicalRegister(MO.getReg())) { + TRI->isPhysicalRegister(MO.getReg()) && + !(MI.isCall() && MO.getReg() == SP)) { // Remove ranges of all aliased registers. for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) for (unsigned ID : OpenRanges.getVarLocs()) diff --git a/test/DebugInfo/AArch64/asan-stack-vars.ll b/test/DebugInfo/AArch64/asan-stack-vars.ll new file mode 100644 index 00000000000..1dff15cb588 --- /dev/null +++ b/test/DebugInfo/AArch64/asan-stack-vars.ll @@ -0,0 +1,326 @@ +; RUN: llc -O0 -filetype=obj -o - %s | llvm-dwarfdump - | FileCheck %s +; +; Derived from (clang -O0 -g -fsanitize=address -fobjc-arc) +; @protocol NSObject +; @end +; @interface NSObject{} +; + (instancetype)alloc; +; @end +; struct CGSize { +; double width; +; double height; +; }; +; typedef struct CGSize CGSize; +; @interface Object : NSObject +; - (instancetype)initWithSize:(CGSize)size; +; - (id)aMessage; +; @end +; @implementation MyObject +; + (id)doWithSize:(CGSize)imageSize andObject:(id)object { +; return [object aMessage]; +; } +; @end +; +; CHECK: .debug_info contents: +; CHECK: DW_TAG_subprogram +; CHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000) +; CHECK-NEXT: DW_AT_high_pc [DW_FORM_addr] ([[FN_END:.*]]) +; CHECK: "_cmd" +; CHECK: DW_TAG_formal_parameter +; CHECK-NEXT: DW_AT_location {{.*}} ([[OFS:.*]]) +; CHECK-NEXT: DW_AT_name {{.*}}"imageSize" +; +; CHECK: .debug_loc contents: +; CHECK: [[OFS]]: Beginning address offset: 0x0000000000000000 +; CHECK_NOT: 0x{{.*}}: Beginning +; CHECK: Ending address offset: [[FN_END]] + +; ModuleID = 'm.m' +source_filename = "m.m" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-ios" + +%0 = type opaque +%struct._class_t = type { %struct._class_t*, %struct._class_t*, %struct._objc_cache*, i8* (i8*, i8*)**, %struct._class_ro_t* } +%struct._objc_cache = type opaque +%struct._class_ro_t = type { i32, i32, i32, i8*, i8*, %struct.__method_list_t*, %struct._objc_protocol_list*, %struct._ivar_list_t*, i8*, %struct._prop_list_t* } +%struct.__method_list_t = type { i32, i32, [0 x %struct._objc_method] } +%struct._objc_method = type { i8*, i8*, i8* } +%struct._objc_protocol_list = type { i64, [0 x %struct._protocol_t*] } +%struct._protocol_t = type { i8*, i8*, %struct._objc_protocol_list*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct.__method_list_t*, %struct._prop_list_t*, i32, i32, i8**, i8*, %struct._prop_list_t* } +%struct._ivar_list_t = type { i32, i32, [0 x %struct._ivar_t] } +%struct._ivar_t = type { i32*, i8*, i8*, i32, i32 } +%struct._prop_list_t = type { i32, i32, [0 x %struct._prop_t] } +%struct._prop_t = type { i8*, i8* } +%struct.CGSize = type { double, double } + +@"OBJC_CLASS_$_Object" = external global %struct._class_t +@"OBJC_CLASSLIST_REFERENCES_$_" = private global %struct._class_t* @"OBJC_CLASS_$_Object", section "__DATA, __objc_classrefs, regular, no_dead_strip", align 8 +@OBJC_METH_VAR_NAME_ = private unnamed_addr constant [6 x i8] c"alloc\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +@OBJC_SELECTOR_REFERENCES_ = private externally_initialized global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip", align 8 +@OBJC_METH_VAR_NAME_.1 = private unnamed_addr constant [14 x i8] c"initWithSize:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +@OBJC_SELECTOR_REFERENCES_.2 = private externally_initialized global i8* getelementptr inbounds ([14 x i8], [14 x i8]* @OBJC_METH_VAR_NAME_.1, i32 0, i32 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip", align 8 +@OBJC_METH_VAR_NAME_.3 = private unnamed_addr constant [9 x i8] c"aMessage\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +@OBJC_SELECTOR_REFERENCES_.4 = private externally_initialized global i8* getelementptr inbounds ([9 x i8], [9 x i8]* @OBJC_METH_VAR_NAME_.3, i32 0, i32 0), section "__DATA, __objc_selrefs, literal_pointers, no_dead_strip", align 8 +@_objc_empty_cache = external global %struct._objc_cache +@"OBJC_CLASS_$_MyObject" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_MyObject", %struct._class_t* null, %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"\01l_OBJC_CLASS_RO_$_MyObject" }, section "__DATA, __objc_data", align 8 +@"OBJC_METACLASS_$_MyObject" = global %struct._class_t { %struct._class_t* @"OBJC_METACLASS_$_MyObject", %struct._class_t* @"OBJC_CLASS_$_MyObject", %struct._objc_cache* @_objc_empty_cache, i8* (i8*, i8*)** null, %struct._class_ro_t* @"\01l_OBJC_METACLASS_RO_$_MyObject" }, section "__DATA, __objc_data", align 8 +@OBJC_CLASS_NAME_ = private unnamed_addr constant [9 x i8] c"MyObject\00", section "__TEXT,__objc_classname,cstring_literals", align 1 +@OBJC_METH_VAR_NAME_.5 = private unnamed_addr constant [12 x i8] c"doWithSize:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 +@OBJC_METH_VAR_TYPE_ = private unnamed_addr constant [21 x i8] c"@32@0:8{CGSize=dd}16\00", section "__TEXT,__objc_methtype,cstring_literals", align 1 +@"\01l_OBJC_$_CLASS_METHODS_MyObject" = private global { i32, i32, [1 x %struct._objc_method] } { i32 24, i32 1, [1 x %struct._objc_method] [%struct._objc_method { i8* getelementptr inbounds ([12 x i8], [12 x i8]* @OBJC_METH_VAR_NAME_.5, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast (i8* (i8*, i8*, [2 x double])* @"\01+[MyObject doWithSize:]" to i8*) }] }, section "__DATA, __objc_const", align 8 +@"\01l_OBJC_METACLASS_RO_$_MyObject" = private global %struct._class_ro_t { i32 131, i32 40, i32 40, i8* null, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* bitcast ({ i32, i32, [1 x %struct._objc_method] }* @"\01l_OBJC_$_CLASS_METHODS_MyObject" to %struct.__method_list_t*), %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8 +@"\01l_OBJC_CLASS_RO_$_MyObject" = private global %struct._class_ro_t { i32 130, i32 0, i32 0, i8* null, i8* getelementptr inbounds ([9 x i8], [9 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), %struct.__method_list_t* null, %struct._objc_protocol_list* null, %struct._ivar_list_t* null, i8* null, %struct._prop_list_t* null }, section "__DATA, __objc_const", align 8 +@"OBJC_LABEL_CLASS_$" = private global [1 x i8*] [i8* bitcast (%struct._class_t* @"OBJC_CLASS_$_MyObject" to i8*)], section "__DATA, __objc_classlist, regular, no_dead_strip", align 8 +@llvm.compiler.used = appending global [12 x i8*] [i8* bitcast (%struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_" to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @OBJC_METH_VAR_NAME_, i32 0, i32 0), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_ to i8*), i8* getelementptr inbounds ([14 x i8], [14 x i8]* @OBJC_METH_VAR_NAME_.1, i32 0, i32 0), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_.2 to i8*), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @OBJC_METH_VAR_NAME_.3, i32 0, i32 0), i8* bitcast (i8** @OBJC_SELECTOR_REFERENCES_.4 to i8*), i8* getelementptr inbounds ([9 x i8], [9 x i8]* @OBJC_CLASS_NAME_, i32 0, i32 0), i8* getelementptr inbounds ([12 x i8], [12 x i8]* @OBJC_METH_VAR_NAME_.5, i32 0, i32 0), i8* getelementptr inbounds ([21 x i8], [21 x i8]* @OBJC_METH_VAR_TYPE_, i32 0, i32 0), i8* bitcast ({ i32, i32, [1 x %struct._objc_method] }* @"\01l_OBJC_$_CLASS_METHODS_MyObject" to i8*), i8* bitcast ([1 x i8*]* @"OBJC_LABEL_CLASS_$" to i8*)], section "llvm.metadata" +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 1, void ()* @asan.module_ctor, i8* null }] +@__asan_shadow_memory_dynamic_address = external global i64 +@__asan_gen_ = private unnamed_addr constant [34 x i8] c"2 32 16 9 imageSize 64 8 6 object\00", align 1 + +; Function Attrs: noinline sanitize_address ssp uwtable +define internal i8* @"\01+[MyObject doWithSize:]"(i8* %self, i8* %_cmd, [2 x double] %imageSize.coerce) #0 !dbg !14 { +entry: + %0 = load i64, i64* @__asan_shadow_memory_dynamic_address + %self.addr = alloca i8*, align 8 + %_cmd.addr = alloca i8*, align 8 + %MyAlloca = alloca [96 x i8], align 32, !dbg !35 + %1 = ptrtoint [96 x i8]* %MyAlloca to i64, !dbg !35 + %2 = add i64 %1, 32, !dbg !35 + %3 = inttoptr i64 %2 to %struct.CGSize*, !dbg !35 + %4 = add i64 %1, 64, !dbg !35 + %5 = inttoptr i64 %4 to %0**, !dbg !35 + %6 = inttoptr i64 %1 to i64*, !dbg !35 + store i64 1102416563, i64* %6, !dbg !35 + %7 = add i64 %1, 8, !dbg !35 + %8 = inttoptr i64 %7 to i64*, !dbg !35 + store i64 ptrtoint ([34 x i8]* @__asan_gen_ to i64), i64* %8, !dbg !35 + %9 = add i64 %1, 16, !dbg !35 + %10 = inttoptr i64 %9 to i64*, !dbg !35 + store i64 ptrtoint (i8* (i8*, i8*, [2 x double])* @"\01+[MyObject doWithSize:]" to i64), i64* %10, !dbg !35 + %11 = lshr i64 %1, 3, !dbg !35 + %12 = add i64 %11, %0, !dbg !35 + %13 = add i64 %12, 0, !dbg !35 + %14 = inttoptr i64 %13 to i64*, !dbg !35 + store i64 -940689368107847183, i64* %14, align 1, !dbg !35 + %15 = add i64 %12, 9, !dbg !35 + %16 = inttoptr i64 %15 to i16*, !dbg !35 + store i16 -3085, i16* %16, align 1, !dbg !35 + %17 = add i64 %12, 11, !dbg !35 + %18 = inttoptr i64 %17 to i8*, !dbg !35 + store i8 -13, i8* %18, align 1, !dbg !35 + call void @llvm.dbg.declare(metadata %struct.CGSize* %3, metadata !36, metadata !37), !dbg !38 + call void @llvm.dbg.declare(metadata %0** %5, metadata !39, metadata !37), !dbg !45 + %19 = bitcast %struct.CGSize* %3 to [2 x double]* + %20 = ptrtoint [2 x double]* %19 to i64 + %21 = lshr i64 %20, 3 + %22 = add i64 %21, %0 + %23 = inttoptr i64 %22 to i16* + %24 = load i16, i16* %23 + %25 = icmp ne i16 %24, 0 + br i1 %25, label %26, label %27 + +;