[llvm] r363635 - hwasan: Add a tag_offset DWARF attribute to instrumented stack variables.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 17 16:39:41 PDT 2019


Author: pcc
Date: Mon Jun 17 16:39:41 2019
New Revision: 363635

URL: http://llvm.org/viewvc/llvm-project?rev=363635&view=rev
Log:
hwasan: Add a tag_offset DWARF attribute to instrumented stack variables.

The goal is to improve hwasan's error reporting for stack use-after-return by
recording enough information to allow the specific variable that was accessed
to be identified based on the pointer's tag. Currently we record the PC and
lower bits of SP for each stack frame we create (which will eventually be
enough to derive the base tag used by the stack frame) but that's not enough
to determine the specific tag for each variable, which is the stack frame's
base tag XOR a value (the "tag offset") that is unique for each variable in
a function.

In IR, the tag offset is most naturally represented as part of a location
expression on the llvm.dbg.declare instruction. However, the presence of the
tag offset in the variable's actual location expression is likely to confuse
debuggers which won't know about tag offsets, and moreover the tag offset
is not required for a debugger to determine the location of the variable on
the stack, so at the DWARF level it is represented as an attribute so that
it will be ignored by debuggers that don't know about it.

Differential Revision: https://reviews.llvm.org/D63119

Added:
    llvm/trunk/test/CodeGen/AArch64/dbg-declare-tag-offset.ll
    llvm/trunk/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/include/llvm/BinaryFormat/Dwarf.def
    llvm/trunk/include/llvm/BinaryFormat/Dwarf.h
    llvm/trunk/lib/BinaryFormat/Dwarf.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp
    llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
    llvm/trunk/test/Assembler/diexpression.ll

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Mon Jun 17 16:39:41 2019
@@ -4704,6 +4704,9 @@ The current supported opcode vocabulary
   (``16`` and ``DW_ATE_signed`` here, respectively) to which the top of the
   expression stack is to be converted. Maps into a ``DW_OP_convert`` operation
   that references a base type constructed from the supplied values.
+- ``DW_OP_LLVM_tag_offset, tag_offset`` specifies that a memory tag should be
+  optionally applied to the pointer. The memory tag is derived from the
+  given tag offset in an implementation-defined manner.
 - ``DW_OP_swap`` swaps top two stack entries.
 - ``DW_OP_xderef`` provides extended dereference mechanism. The entry at the top
   of the stack is treated as an address. The second stack entry is treated as an

Modified: llvm/trunk/include/llvm/BinaryFormat/Dwarf.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Dwarf.def?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Dwarf.def (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Dwarf.def Mon Jun 17 16:39:41 2019
@@ -386,6 +386,7 @@ HANDLE_DW_AT(0x3b31, BORLAND_closure, 0,
 HANDLE_DW_AT(0x3e00, LLVM_include_path, 0, LLVM)
 HANDLE_DW_AT(0x3e01, LLVM_config_macros, 0, LLVM)
 HANDLE_DW_AT(0x3e02, LLVM_isysroot, 0, LLVM)
+HANDLE_DW_AT(0x3e03, LLVM_tag_offset, 0, LLVM)
 // Apple extensions.
 HANDLE_DW_AT(0x3fe1, APPLE_optimized, 0, APPLE)
 HANDLE_DW_AT(0x3fe2, APPLE_flags, 0, APPLE)

Modified: llvm/trunk/include/llvm/BinaryFormat/Dwarf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Dwarf.h?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Dwarf.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Dwarf.h Mon Jun 17 16:39:41 2019
@@ -129,8 +129,9 @@ enum LocationAtom {
 #include "llvm/BinaryFormat/Dwarf.def"
   DW_OP_lo_user = 0xe0,
   DW_OP_hi_user = 0xff,
-  DW_OP_LLVM_fragment = 0x1000, ///< Only used in LLVM metadata.
-  DW_OP_LLVM_convert  = 0x1001  ///< Only used in LLVM metadata.
+  DW_OP_LLVM_fragment = 0x1000,   ///< Only used in LLVM metadata.
+  DW_OP_LLVM_convert = 0x1001,    ///< Only used in LLVM metadata.
+  DW_OP_LLVM_tag_offset = 0x1002, ///< Only used in LLVM metadata.
 };
 
 enum TypeKind : uint8_t {

Modified: llvm/trunk/lib/BinaryFormat/Dwarf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/BinaryFormat/Dwarf.cpp?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/lib/BinaryFormat/Dwarf.cpp (original)
+++ llvm/trunk/lib/BinaryFormat/Dwarf.cpp Mon Jun 17 16:39:41 2019
@@ -147,6 +147,8 @@ StringRef llvm::dwarf::OperationEncoding
     return "DW_OP_LLVM_convert";
   case DW_OP_LLVM_fragment:
     return "DW_OP_LLVM_fragment";
+  case DW_OP_LLVM_tag_offset:
+    return "DW_OP_LLVM_tag_offset";
   }
 }
 
@@ -157,6 +159,7 @@ unsigned llvm::dwarf::getOperationEncodi
 #include "llvm/BinaryFormat/Dwarf.def"
       .Case("DW_OP_LLVM_convert", DW_OP_LLVM_convert)
       .Case("DW_OP_LLVM_fragment", DW_OP_LLVM_fragment)
+      .Case("DW_OP_LLVM_tag_offset", DW_OP_LLVM_tag_offset)
       .Default(0);
 }
 

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Mon Jun 17 16:39:41 2019
@@ -683,6 +683,9 @@ DIE *DwarfCompileUnit::constructVariable
             NVPTXAddressSpace ? *NVPTXAddressSpace : NVPTX_ADDR_local_space);
   }
   addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+  if (DwarfExpr.TagOffset)
+    addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
+            *DwarfExpr.TagOffset);
 
   return VariableDie;
 }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.cpp Mon Jun 17 16:39:41 2019
@@ -438,6 +438,9 @@ void DwarfExpression::addExpression(DIEx
       emitOp(dwarf::DW_OP_deref_size);
       emitData1(Op->getArg(0));
       break;
+    case dwarf::DW_OP_LLVM_tag_offset:
+      TagOffset = Op->getArg(0);
+      break;
     default:
       llvm_unreachable("unhandled opcode found in expression");
     }

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfExpression.h Mon Jun 17 16:39:41 2019
@@ -140,6 +140,8 @@ public:
     return LocationKind == Implicit;
   }
 
+  Optional<uint8_t> TagOffset;
+
 protected:
   /// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
   /// to represent a subregister.

Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Mon Jun 17 16:39:41 2019
@@ -835,6 +835,7 @@ unsigned DIExpression::ExprOperand::getS
   case dwarf::DW_OP_constu:
   case dwarf::DW_OP_deref_size:
   case dwarf::DW_OP_plus_uconst:
+  case dwarf::DW_OP_LLVM_tag_offset:
     return 2;
   default:
     return 1;
@@ -876,6 +877,7 @@ bool DIExpression::isValid() const {
       break;
     }
     case dwarf::DW_OP_LLVM_convert:
+    case dwarf::DW_OP_LLVM_tag_offset:
     case dwarf::DW_OP_constu:
     case dwarf::DW_OP_plus_uconst:
     case dwarf::DW_OP_plus:
@@ -905,7 +907,9 @@ bool DIExpression::isImplicit() const {
   unsigned N = getNumElements();
   if (isValid() && N > 0) {
     switch (getElement(N-1)) {
-      case dwarf::DW_OP_stack_value: return true;
+      case dwarf::DW_OP_stack_value:
+      case dwarf::DW_OP_LLVM_tag_offset:
+        return true;
       case dwarf::DW_OP_LLVM_fragment:
         return N > 1 && getElement(N-2) == dwarf::DW_OP_stack_value;
       default: break;

Modified: llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp (original)
+++ llvm/trunk/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp Mon Jun 17 16:39:41 2019
@@ -21,6 +21,7 @@
 #include "llvm/IR/Constant.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
@@ -205,8 +206,10 @@ public:
   bool tagAlloca(IRBuilder<> &IRB, AllocaInst *AI, Value *Tag);
   Value *tagPointer(IRBuilder<> &IRB, Type *Ty, Value *PtrLong, Value *Tag);
   Value *untagPointer(IRBuilder<> &IRB, Value *PtrLong);
-  bool instrumentStack(SmallVectorImpl<AllocaInst *> &Allocas,
-                       SmallVectorImpl<Instruction *> &RetVec, Value *StackTag);
+  bool instrumentStack(
+      SmallVectorImpl<AllocaInst *> &Allocas,
+      DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
+      SmallVectorImpl<Instruction *> &RetVec, Value *StackTag);
   bool instrumentLandingPads(SmallVectorImpl<Instruction *> &RetVec);
   Value *getNextTagWithCall(IRBuilder<> &IRB);
   Value *getStackBaseTag(IRBuilder<> &IRB);
@@ -984,6 +987,7 @@ bool HWAddressSanitizer::instrumentLandi
 
 bool HWAddressSanitizer::instrumentStack(
     SmallVectorImpl<AllocaInst *> &Allocas,
+    DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> &AllocaDeclareMap,
     SmallVectorImpl<Instruction *> &RetVec, Value *StackTag) {
   // Ideally, we want to calculate tagged stack base pointer, and rewrite all
   // alloca addresses using that. Unfortunately, offsets are not known yet
@@ -1008,6 +1012,13 @@ bool HWAddressSanitizer::instrumentStack
         U.set(Replacement);
     }
 
+    for (auto *DDI : AllocaDeclareMap.lookup(AI)) {
+      DIExpression *OldExpr = DDI->getExpression();
+      DIExpression *NewExpr = DIExpression::append(
+          OldExpr, {dwarf::DW_OP_LLVM_tag_offset, RetagMask(N)});
+      DDI->setArgOperand(2, MetadataAsValue::get(*C, NewExpr));
+    }
+
     tagAlloca(IRB, AI, Tag);
 
     for (auto RI : RetVec) {
@@ -1051,6 +1062,7 @@ bool HWAddressSanitizer::sanitizeFunctio
   SmallVector<AllocaInst*, 8> AllocasToInstrument;
   SmallVector<Instruction*, 8> RetVec;
   SmallVector<Instruction*, 8> LandingPadVec;
+  DenseMap<AllocaInst *, std::vector<DbgDeclareInst *>> AllocaDeclareMap;
   for (auto &BB : F) {
     for (auto &Inst : BB) {
       if (ClInstrumentStack)
@@ -1069,6 +1081,10 @@ bool HWAddressSanitizer::sanitizeFunctio
           isa<CleanupReturnInst>(Inst))
         RetVec.push_back(&Inst);
 
+      if (auto *DDI = dyn_cast<DbgDeclareInst>(&Inst))
+        if (auto *Alloca = dyn_cast_or_null<AllocaInst>(DDI->getAddress()))
+          AllocaDeclareMap[Alloca].push_back(DDI);
+
       if (ClInstrumentLandingPads && isa<LandingPadInst>(Inst))
         LandingPadVec.push_back(&Inst);
 
@@ -1107,7 +1123,8 @@ bool HWAddressSanitizer::sanitizeFunctio
   if (!AllocasToInstrument.empty()) {
     Value *StackTag =
         ClGenerateTagsWithCalls ? nullptr : getStackBaseTag(EntryIRB);
-    Changed |= instrumentStack(AllocasToInstrument, RetVec, StackTag);
+    Changed |= instrumentStack(AllocasToInstrument, AllocaDeclareMap, RetVec,
+                               StackTag);
   }
 
   // If we split the entry block, move any allocas that were originally in the

Modified: llvm/trunk/test/Assembler/diexpression.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/diexpression.ll?rev=363635&r1=363634&r2=363635&view=diff
==============================================================================
--- llvm/trunk/test/Assembler/diexpression.ll (original)
+++ llvm/trunk/test/Assembler/diexpression.ll Mon Jun 17 16:39:41 2019
@@ -9,9 +9,10 @@
 ; CHECK-SAME: !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 3, DW_OP_LLVM_fragment, 3, 7),
 ; CHECK-SAME: !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef),
 ; CHECK-SAME: !DIExpression(DW_OP_plus_uconst, 3)
-; CHECK-SAME: !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_signed)}
+; CHECK-SAME: !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_signed)
+; CHECK-SAME: !DIExpression(DW_OP_LLVM_tag_offset, 1)}
 
-!named = !{!0, !1, !2, !3, !4, !5, !6, !7}
+!named = !{!0, !1, !2, !3, !4, !5, !6, !7, !8}
 
 !0 = !DIExpression()
 !1 = !DIExpression(DW_OP_deref)
@@ -21,3 +22,4 @@
 !5 = !DIExpression(DW_OP_constu, 2, DW_OP_swap, DW_OP_xderef)
 !6 = !DIExpression(DW_OP_plus_uconst, 3)
 !7 = !DIExpression(DW_OP_LLVM_convert, 16, DW_ATE_unsigned, DW_OP_LLVM_convert, 32, DW_ATE_signed)
+!8 = !DIExpression(DW_OP_LLVM_tag_offset, 1)

Added: llvm/trunk/test/CodeGen/AArch64/dbg-declare-tag-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/dbg-declare-tag-offset.ll?rev=363635&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/dbg-declare-tag-offset.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/dbg-declare-tag-offset.ll Mon Jun 17 16:39:41 2019
@@ -0,0 +1,47 @@
+; RUN: llc -o - %s | FileCheck %s
+
+target triple="aarch64--"
+
+; CHECK: .Linfo_string4:
+; CHECK-NEXT: .asciz "a"
+; CHECK: .Linfo_string6:
+; CHECK-NEXT: .asciz "b"
+
+; CHECK: .byte 1 // DW_AT_LLVM_tag_offset
+; CHECK: .word .Linfo_string4 // DW_AT_name
+
+; CHECK: .byte 2 // DW_AT_LLVM_tag_offset
+; CHECK: .word .Linfo_string6 // DW_AT_name
+
+define void @f() !dbg !6 {
+entry:
+  %a = alloca i8*
+  %b = alloca i8*
+  call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression(DW_OP_LLVM_tag_offset, 1)), !dbg !14
+  call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression(DW_OP_LLVM_tag_offset, 2)), !dbg !14
+  ret void, !dbg !15
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "x.c", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang"}
+!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags:
+DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!7 = !DISubroutineType(types: !8)
+!8 = !{null, !9}
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11)
+!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!12 = !DILocalVariable(name: "a", scope: !6, file: !1, line: 1, type: !9)
+!13 = !DILocalVariable(name: "b", scope: !6, file: !1, line: 1, type: !9)
+!14 = !DILocation(line: 1, column: 29, scope: !6)
+!15 = !DILocation(line: 1, column: 37, scope: !6)

Added: llvm/trunk/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll?rev=363635&view=auto
==============================================================================
--- llvm/trunk/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll (added)
+++ llvm/trunk/test/Instrumentation/HWAddressSanitizer/dbg-declare-tag-offset.ll Mon Jun 17 16:39:41 2019
@@ -0,0 +1,50 @@
+; RUN: opt -hwasan -S -o - %s | FileCheck %s
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64--linux-android"
+
+declare void @g(i8**, i8**, i8**, i8**, i8**, i8**)
+
+define void @f() sanitize_hwaddress !dbg !6 {
+entry:
+  %nodebug0 = alloca i8*
+  %nodebug1 = alloca i8*
+  %nodebug2 = alloca i8*
+  %nodebug3 = alloca i8*
+  %a = alloca i8*
+  %b = alloca i8*
+  ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 4)
+  call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14
+  ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 4)
+  call void @llvm.dbg.declare(metadata i8** %a, metadata !12, metadata !DIExpression()), !dbg !14
+  ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 6)
+  call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14
+  ; CHECK: @llvm.dbg.declare{{.*}} !DIExpression(DW_OP_LLVM_tag_offset, 6)
+  call void @llvm.dbg.declare(metadata i8** %b, metadata !13, metadata !DIExpression()), !dbg !14
+  call void @g(i8** %nodebug0, i8** %nodebug1, i8** %nodebug2, i8** %nodebug3, i8** %a, i8** %b)
+  ret void, !dbg !15
+}
+
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+!llvm.ident = !{!5}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "x.c", directory: "/")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{!"clang"}
+!6 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !7, isLocal: false, isDefinition: true, scopeLine: 1, flags:
+DIFlagPrototyped, isOptimized: false, unit: !0, retainedNodes: !2)
+!7 = !DISubroutineType(types: !8)
+!8 = !{null, !9}
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11)
+!11 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!12 = !DILocalVariable(name: "a", scope: !6, file: !1, line: 1, type: !9)
+!13 = !DILocalVariable(name: "b", scope: !6, file: !1, line: 1, type: !9)
+!14 = !DILocation(line: 1, column: 29, scope: !6)
+!15 = !DILocation(line: 1, column: 37, scope: !6)




More information about the llvm-commits mailing list