OSDN Git Service

llvm-symbolizer: Add a FRAME command.
authorPeter Collingbourne <peter@pcc.me.uk>
Mon, 24 Jun 2019 20:03:23 +0000 (20:03 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Mon, 24 Jun 2019 20:03:23 +0000 (20:03 +0000)
This command prints a description of the referenced function's stack frame.
For each formal parameter and local variable, the tool prints:

- function name
- variable name
- file/line of declaration
- FP-relative variable location (if available)
- size in bytes
- HWASAN tag offset

This information will be used by the HWASAN runtime to identify local
variables in UAR reports.

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

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

16 files changed:
include/llvm/DebugInfo/DIContext.h
include/llvm/DebugInfo/DWARF/DWARFContext.h
include/llvm/DebugInfo/PDB/PDBContext.h
include/llvm/DebugInfo/Symbolize/DIPrinter.h
include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
include/llvm/DebugInfo/Symbolize/Symbolize.h
lib/DebugInfo/DWARF/DWARFContext.cpp
lib/DebugInfo/PDB/PDBContext.cpp
lib/DebugInfo/Symbolize/DIPrinter.cpp
lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
lib/DebugInfo/Symbolize/Symbolize.cpp
test/tools/llvm-symbolizer/frame-fortran.s [new file with mode: 0644]
test/tools/llvm-symbolizer/frame-types.s [new file with mode: 0644]
test/tools/llvm-symbolizer/frame.s [new file with mode: 0644]
tools/llvm-symbolizer/llvm-symbolizer.cpp

index b3f7739..d2a5318 100644 (file)
@@ -112,6 +112,16 @@ struct DIGlobal {
   DIGlobal() : Name("<invalid>") {}
 };
 
+struct DILocal {
+  std::string FunctionName;
+  std::string Name;
+  std::string DeclFile;
+  uint64_t DeclLine = 0;
+  Optional<int64_t> FrameOffset;
+  Optional<uint64_t> Size;
+  Optional<uint64_t> TagOffset;
+};
+
 /// A DINameKind is passed to name search methods to specify a
 /// preference regarding the type of name resolution the caller wants.
 enum class DINameKind { None, ShortName, LinkageName };
@@ -216,6 +226,9 @@ public:
       object::SectionedAddress Address,
       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0;
 
+  virtual std::vector<DILocal>
+  getLocalsForAddress(object::SectionedAddress Address) = 0;
+
 private:
   const DIContextKind Kind;
 };
index 5d243da..23cf21c 100644 (file)
@@ -331,6 +331,9 @@ public:
       object::SectionedAddress Address,
       DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
 
+  std::vector<DILocal>
+  getLocalsForAddress(object::SectionedAddress Address) override;
+
   bool isLittleEndian() const { return DObj->isLittleEndian(); }
   static bool isSupportedVersion(unsigned version) {
     return version == 2 || version == 3 || version == 4 || version == 5;
@@ -374,6 +377,8 @@ private:
   /// TODO: change input parameter from "uint64_t Address"
   ///       into "SectionedAddress Address"
   DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
+  void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
+                       std::vector<DILocal> &Result);
 };
 
 } // end namespace llvm
index 89a7efe..7b6793f 100644 (file)
@@ -52,6 +52,9 @@ namespace pdb {
         object::SectionedAddress Address,
         DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
 
+    std::vector<DILocal>
+    getLocalsForAddress(object::SectionedAddress Address) override;
+
   private:
     std::string getFunctionName(uint64_t Address, DINameKind NameKind) const;
     std::unique_ptr<IPDBSession> Session;
index 8bc8dd2..db7a61a 100644 (file)
@@ -20,6 +20,7 @@ namespace llvm {
 struct DILineInfo;
 class DIInliningInfo;
 struct DIGlobal;
+struct DILocal;
 
 namespace symbolize {
 
@@ -51,6 +52,7 @@ public:
   DIPrinter &operator<<(const DILineInfo &Info);
   DIPrinter &operator<<(const DIInliningInfo &Info);
   DIPrinter &operator<<(const DIGlobal &Global);
+  DIPrinter &operator<<(const DILocal &Local);
 };
 }
 }
index 2bdfb09..506ecc4 100644 (file)
@@ -32,6 +32,8 @@ public:
                        FunctionNameKind FNKind, bool UseSymbolTable) const = 0;
   virtual DIGlobal
   symbolizeData(object::SectionedAddress ModuleOffset) const = 0;
+  virtual std::vector<DILocal>
+  symbolizeFrame(object::SectionedAddress ModuleOffset) const = 0;
 
   // Return true if this is a 32-bit x86 PE COFF module.
   virtual bool isWin32Module() const = 0;
index c954cc6..befedfa 100644 (file)
@@ -59,6 +59,9 @@ public:
                        object::SectionedAddress ModuleOffset);
   Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
                                    object::SectionedAddress ModuleOffset);
+  Expected<std::vector<DILocal>>
+  symbolizeFrame(const std::string &ModuleName,
+                 object::SectionedAddress ModuleOffset);
   void flush();
 
   static std::string
index 09a42a6..321e157 100644 (file)
@@ -41,6 +41,7 @@
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/LEB128.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -972,6 +973,124 @@ static bool getFunctionNameAndStartLineForAddress(DWARFCompileUnit *CU,
   return FoundResult;
 }
 
+static Optional<uint64_t> getTypeSize(DWARFDie Type, uint64_t PointerSize) {
+  if (auto SizeAttr = Type.find(DW_AT_byte_size))
+    if (Optional<uint64_t> Size = SizeAttr->getAsUnsignedConstant())
+      return Size;
+
+  switch (Type.getTag()) {
+  case DW_TAG_pointer_type:
+  case DW_TAG_reference_type:
+  case DW_TAG_rvalue_reference_type:
+    return PointerSize;
+  case DW_TAG_ptr_to_member_type: {
+    if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type))
+      if (BaseType.getTag() == DW_TAG_subroutine_type)
+        return 2 * PointerSize;
+    return PointerSize;
+  }
+  case DW_TAG_const_type:
+  case DW_TAG_volatile_type:
+  case DW_TAG_restrict_type:
+  case DW_TAG_typedef: {
+    if (DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type))
+      return getTypeSize(BaseType, PointerSize);
+    break;
+  }
+  case DW_TAG_array_type: {
+    DWARFDie BaseType = Type.getAttributeValueAsReferencedDie(DW_AT_type);
+    if (!BaseType)
+      return Optional<uint64_t>();
+    Optional<uint64_t> BaseSize = getTypeSize(BaseType, PointerSize);
+    if (!BaseSize)
+      return Optional<uint64_t>();
+    uint64_t Size = *BaseSize;
+    for (DWARFDie Child : Type) {
+      if (Child.getTag() != DW_TAG_subrange_type)
+        continue;
+
+      if (auto ElemCountAttr = Child.find(DW_AT_count))
+        if (Optional<uint64_t> ElemCount =
+                ElemCountAttr->getAsUnsignedConstant())
+          Size *= *ElemCount;
+      if (auto UpperBoundAttr = Child.find(DW_AT_upper_bound))
+        if (Optional<int64_t> UpperBound =
+                UpperBoundAttr->getAsSignedConstant()) {
+          int64_t LowerBound = 0;
+          if (auto LowerBoundAttr = Child.find(DW_AT_lower_bound))
+            LowerBound = LowerBoundAttr->getAsSignedConstant().getValueOr(0);
+          Size *= *UpperBound - LowerBound + 1;
+        }
+    }
+    return Size;
+  }
+  default:
+    break;
+  }
+  return Optional<uint64_t>();
+}
+
+void DWARFContext::addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram,
+                                   DWARFDie Die, std::vector<DILocal> &Result) {
+  if (Die.getTag() == DW_TAG_variable ||
+      Die.getTag() == DW_TAG_formal_parameter) {
+    DILocal Local;
+    if (auto NameAttr = Subprogram.find(DW_AT_name))
+      if (Optional<const char *> Name = NameAttr->getAsCString())
+        Local.FunctionName = *Name;
+    if (auto LocationAttr = Die.find(DW_AT_location))
+      if (Optional<ArrayRef<uint8_t>> Location = LocationAttr->getAsBlock())
+        if (!Location->empty() && (*Location)[0] == DW_OP_fbreg)
+          Local.FrameOffset =
+              decodeSLEB128(Location->data() + 1, nullptr, Location->end());
+    if (auto TagOffsetAttr = Die.find(DW_AT_LLVM_tag_offset))
+      Local.TagOffset = TagOffsetAttr->getAsUnsignedConstant();
+
+    if (auto Origin =
+            Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+      Die = Origin;
+    if (auto NameAttr = Die.find(DW_AT_name))
+      if (Optional<const char *> Name = NameAttr->getAsCString())
+        Local.Name = *Name;
+    if (auto Type = Die.getAttributeValueAsReferencedDie(DW_AT_type))
+      Local.Size = getTypeSize(Type, getCUAddrSize());
+    if (auto DeclFileAttr = Die.find(DW_AT_decl_file)) {
+      if (const auto *LT = CU->getContext().getLineTableForUnit(CU))
+        LT->getFileNameByIndex(
+            DeclFileAttr->getAsUnsignedConstant().getValue(),
+            CU->getCompilationDir(),
+            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+            Local.DeclFile);
+    }
+    if (auto DeclLineAttr = Die.find(DW_AT_decl_line))
+      Local.DeclLine = DeclLineAttr->getAsUnsignedConstant().getValue();
+
+    Result.push_back(Local);
+    return;
+  }
+
+  if (Die.getTag() == DW_TAG_inlined_subroutine)
+    if (auto Origin =
+            Die.getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+      Subprogram = Origin;
+
+  for (auto Child : Die)
+    addLocalsForDie(CU, Subprogram, Child, Result);
+}
+
+std::vector<DILocal>
+DWARFContext::getLocalsForAddress(object::SectionedAddress Address) {
+  std::vector<DILocal> Result;
+  DWARFCompileUnit *CU = getCompileUnitForAddress(Address.Address);
+  if (!CU)
+    return Result;
+
+  DWARFDie Subprogram = CU->getSubroutineForAddress(Address.Address);
+  if (Subprogram.isValid())
+    addLocalsForDie(CU, Subprogram, Subprogram, Result);
+  return Result;
+}
+
 DILineInfo DWARFContext::getLineInfoForAddress(object::SectionedAddress Address,
                                                DILineInfoSpecifier Spec) {
   DILineInfo Result;
index 89c20e6..e452f1d 100644 (file)
@@ -91,6 +91,11 @@ PDBContext::getInliningInfoForAddress(object::SectionedAddress Address,
   return InlineInfo;
 }
 
+std::vector<DILocal>
+PDBContext::getLocalsForAddress(object::SectionedAddress Address) {
+  return std::vector<DILocal>();
+}
+
 std::string PDBContext::getFunctionName(uint64_t Address,
                                         DINameKind NameKind) const {
   if (NameKind == DINameKind::None)
index f6c7ef8..b2bfef2 100644 (file)
@@ -122,5 +122,28 @@ DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
   return *this;
 }
 
+DIPrinter &DIPrinter::operator<<(const DILocal &Local) {
+  OS << Local.FunctionName << '\n';
+  OS << Local.Name << '\n';
+  if (Local.DeclFile.empty())
+    OS << "??";
+  else
+    OS << Local.DeclFile;
+  OS << ':' << Local.DeclLine << '\n';
+  if (Local.FrameOffset)
+    OS << *Local.FrameOffset << ' ';
+  else
+    OS << "?? ";
+  if (Local.Size)
+    OS << *Local.Size << ' ';
+  else
+    OS << "?? ";
+  if (Local.TagOffset)
+    OS << *Local.TagOffset << '\n';
+  else
+    OS << "??\n";
+  return *this;
+}
+
 } // end namespace symbolize
 } // end namespace llvm
index 62f849f..6092584 100644 (file)
@@ -298,6 +298,14 @@ DIGlobal SymbolizableObjectFile::symbolizeData(
   return Res;
 }
 
+std::vector<DILocal> SymbolizableObjectFile::symbolizeFrame(
+    object::SectionedAddress ModuleOffset) const {
+  if (ModuleOffset.SectionIndex == object::SectionedAddress::UndefSection)
+    ModuleOffset.SectionIndex =
+        getModuleSectionIndexForAddress(ModuleOffset.Address);
+  return DebugInfoContext->getLocalsForAddress(ModuleOffset);
+}
+
 /// Search for the first occurence of specified Address in ObjectFile.
 uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress(
     uint64_t Address) const {
index d5510cb..3a511dc 100644 (file)
@@ -40,6 +40,8 @@ public:
                                       FunctionNameKind FNKind,
                                       bool UseSymbolTable) const override;
   DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override;
+  std::vector<DILocal>
+  symbolizeFrame(object::SectionedAddress ModuleOffset) const override;
 
   // Return true if this is a 32-bit x86 PE COFF module.
   bool isWin32Module() const override;
index 1bfd4e8..1cb8a7a 100644 (file)
@@ -133,6 +133,29 @@ LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
   return Global;
 }
 
+Expected<std::vector<DILocal>>
+LLVMSymbolizer::symbolizeFrame(const std::string &ModuleName,
+                               object::SectionedAddress ModuleOffset) {
+  SymbolizableModule *Info;
+  if (auto InfoOrErr = getOrCreateModuleInfo(ModuleName))
+    Info = InfoOrErr.get();
+  else
+    return InfoOrErr.takeError();
+
+  // A null module means an error has already been reported. Return an empty
+  // result.
+  if (!Info)
+    return std::vector<DILocal>();
+
+  // If the user is giving us relative addresses, add the preferred base of
+  // the object to the offset before we do the query. It's what DIContext
+  // expects.
+  if (Opts.RelativeAddresses)
+    ModuleOffset.Address += Info->getModulePreferredBase();
+
+  return Info->symbolizeFrame(ModuleOffset);
+}
+
 void LLVMSymbolizer::flush() {
   ObjectForUBPathAndArch.clear();
   BinaryForPath.clear();
diff --git a/test/tools/llvm-symbolizer/frame-fortran.s b/test/tools/llvm-symbolizer/frame-fortran.s
new file mode 100644 (file)
index 0000000..21c8d66
--- /dev/null
@@ -0,0 +1,230 @@
+// REQUIRES: x86-registered-target
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -o %t.o %s
+// RUN: echo 'FRAME %t.o 0' | llvm-symbolizer | FileCheck %s
+
+// Generated with:
+//
+// function foo(array)
+//   integer, intent(in), dimension(2:3) :: array
+// end function foo
+//
+// gcc -x f95 -g -S
+
+// CHECK: foo
+// CHECK-NEXT: array
+// CHECK-NEXT: /home/ubuntu/./example.cpp:1
+// CHECK-NEXT: -24 8 ??
+
+        .file   "example.cpp"
+        .text
+.Ltext0:
+        .globl  foo_
+        .type   foo_, @function
+foo_:
+.LFB0:
+        .file 1 "./example.cpp"
+        .loc 1 1 0
+        .cfi_startproc
+        pushq   %rbp
+        .cfi_def_cfa_offset 16
+        .cfi_offset 6, -16
+        movq    %rsp, %rbp
+        .cfi_def_cfa_register 6
+        movq    %rdi, -8(%rbp)
+        .loc 1 3 0
+        nop
+        popq    %rbp
+        .cfi_def_cfa 7, 8
+        ret
+        .cfi_endproc
+.LFE0:
+        .size   foo_, .-foo_
+.Letext0:
+        .section        .debug_info,"",@progbits
+.Ldebug_info0:
+        .long   0x86
+        .value  0x4
+        .long   .Ldebug_abbrev0
+        .byte   0x8
+        .uleb128 0x1
+        .long   .LASF3
+        .byte   0xe
+        .byte   0x2
+        .long   .LASF4
+        .long   .LASF5
+        .quad   .Ltext0
+        .quad   .Letext0-.Ltext0
+        .long   .Ldebug_line0
+        .uleb128 0x2
+        .string "foo"
+        .byte   0x1
+        .byte   0x1
+        .long   .LASF6
+        .long   0x63
+        .quad   .LFB0
+        .quad   .LFE0-.LFB0
+        .uleb128 0x1
+        .byte   0x9c
+        .long   0x63
+        .uleb128 0x3
+        .long   .LASF7
+        .byte   0x1
+        .byte   0x1
+        .long   0x6a
+        .uleb128 0x3
+        .byte   0x91
+        .sleb128 -24
+        .byte   0x6
+        .byte   0
+        .uleb128 0x4
+        .byte   0x4
+        .byte   0x4
+        .long   .LASF0
+        .uleb128 0x5
+        .long   0x82
+        .long   0x7b
+        .uleb128 0x6
+        .long   0x7b
+        .sleb128 2
+        .sleb128 3
+        .byte   0
+        .uleb128 0x4
+        .byte   0x8
+        .byte   0x5
+        .long   .LASF1
+        .uleb128 0x4
+        .byte   0x4
+        .byte   0x5
+        .long   .LASF2
+        .byte   0
+        .section        .debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+        .uleb128 0x1
+        .uleb128 0x11
+        .byte   0x1
+        .uleb128 0x25
+        .uleb128 0xe
+        .uleb128 0x13
+        .uleb128 0xb
+        .uleb128 0x42
+        .uleb128 0xb
+        .uleb128 0x3
+        .uleb128 0xe
+        .uleb128 0x1b
+        .uleb128 0xe
+        .uleb128 0x11
+        .uleb128 0x1
+        .uleb128 0x12
+        .uleb128 0x7
+        .uleb128 0x10
+        .uleb128 0x17
+        .byte   0
+        .byte   0
+        .uleb128 0x2
+        .uleb128 0x2e
+        .byte   0x1
+        .uleb128 0x3f
+        .uleb128 0x19
+        .uleb128 0x3
+        .uleb128 0x8
+        .uleb128 0x3a
+        .uleb128 0xb
+        .uleb128 0x3b
+        .uleb128 0xb
+        .uleb128 0x6e
+        .uleb128 0xe
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x11
+        .uleb128 0x1
+        .uleb128 0x12
+        .uleb128 0x7
+        .uleb128 0x40
+        .uleb128 0x18
+        .uleb128 0x2117
+        .uleb128 0x19
+        .uleb128 0x1
+        .uleb128 0x13
+        .byte   0
+        .byte   0
+        .uleb128 0x3
+        .uleb128 0x5
+        .byte   0
+        .uleb128 0x3
+        .uleb128 0xe
+        .uleb128 0x3a
+        .uleb128 0xb
+        .uleb128 0x3b
+        .uleb128 0xb
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x2
+        .uleb128 0x18
+        .byte   0
+        .byte   0
+        .uleb128 0x4
+        .uleb128 0x24
+        .byte   0
+        .uleb128 0xb
+        .uleb128 0xb
+        .uleb128 0x3e
+        .uleb128 0xb
+        .uleb128 0x3
+        .uleb128 0xe
+        .byte   0
+        .byte   0
+        .uleb128 0x5
+        .uleb128 0x1
+        .byte   0x1
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x1
+        .uleb128 0x13
+        .byte   0
+        .byte   0
+        .uleb128 0x6
+        .uleb128 0x21
+        .byte   0
+        .uleb128 0x49
+        .uleb128 0x13
+        .uleb128 0x22
+        .uleb128 0xd
+        .uleb128 0x2f
+        .uleb128 0xd
+        .byte   0
+        .byte   0
+        .byte   0
+        .section        .debug_aranges,"",@progbits
+        .long   0x2c
+        .value  0x2
+        .long   .Ldebug_info0
+        .byte   0x8
+        .byte   0
+        .value  0
+        .value  0
+        .quad   .Ltext0
+        .quad   .Letext0-.Ltext0
+        .quad   0
+        .quad   0
+        .section        .debug_line,"",@progbits
+.Ldebug_line0:
+        .section        .debug_str,"MS",@progbits,1
+.LASF5:
+        .string "/home/ubuntu"
+.LASF7:
+        .string "array"
+.LASF0:
+        .string "real(kind=4)"
+.LASF2:
+        .string "integer(kind=4)"
+.LASF6:
+        .string "foo_"
+.LASF1:
+        .string "integer(kind=8)"
+.LASF3:
+        .string "GNU Fortran2008 9.1.0 -mtune=generic -march=x86-64 -g -g -fintrinsic-modules-path /opt/compiler-explorer/gcc-9.1.0/bin/../lib/gcc/x86_64-linux-gnu/9.1.0/finclude"
+.LASF4:
+        .string "./example.cpp"
+        .ident  "GCC: (Compiler-Explorer-Build) 9.1.0"
+        .section        .note.GNU-stack,"",@progbits
diff --git a/test/tools/llvm-symbolizer/frame-types.s b/test/tools/llvm-symbolizer/frame-types.s
new file mode 100644 (file)
index 0000000..cb10f1f
--- /dev/null
@@ -0,0 +1,532 @@
+// REQUIRES: x86-registered-target
+
+// RUN: llvm-mc -filetype=obj -triple=i386-linux-gnu -o %t.o %s
+// RUN: echo 'FRAME %t.o 0' | llvm-symbolizer | FileCheck %s
+
+// CHECK: f
+// CHECK-NEXT: a
+// CHECK-NEXT: /tmp/frame-types.cpp:4
+// CHECK-NEXT: -1 1 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: b
+// CHECK-NEXT: /tmp/frame-types.cpp:5
+// CHECK-NEXT: -8 4 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: c
+// CHECK-NEXT: /tmp/frame-types.cpp:6
+// CHECK-NEXT: -12 4 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: d
+// CHECK-NEXT: /tmp/frame-types.cpp:7
+// CHECK-NEXT: -16 4 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: e
+// CHECK-NEXT: /tmp/frame-types.cpp:8
+// CHECK-NEXT: -32 8 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: f
+// CHECK-NEXT: /tmp/frame-types.cpp:9
+// CHECK-NEXT: -36 4 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: g
+// CHECK-NEXT: /tmp/frame-types.cpp:10
+// CHECK-NEXT: -37 1 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: h
+// CHECK-NEXT: /tmp/frame-types.cpp:11
+// CHECK-NEXT: -38 1 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: i
+// CHECK-NEXT: /tmp/frame-types.cpp:12
+// CHECK-NEXT: -44 4 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: j
+// CHECK-NEXT: /tmp/frame-types.cpp:14
+// CHECK-NEXT: -45 1 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: k
+// CHECK-NEXT: /tmp/frame-types.cpp:15
+// CHECK-NEXT: -57 12 ??
+// CHECK-NEXT: f
+// CHECK-NEXT: l
+// CHECK-NEXT: /tmp/frame-types.cpp:16
+// CHECK-NEXT: -345 288 ??
+
+// Generated from:
+//
+// struct S;
+//
+// void f() {
+//   char a;
+//   char *b;
+//   char &c = a;
+//   char &&d = 1;
+//   char (S::*e)();
+//   char S::*f;
+//   const char g = 2;
+//   volatile char h;
+//   char *__restrict i;
+//   typedef char char_typedef;
+//   char_typedef j;
+//   char k[12];
+//   char l[12][24];
+// }
+//
+// clang++ --target=i386-linux-gnu frame-types.cpp -g -std=c++11 -S -o frame-types.s 
+
+       .text
+       .file   "frame-types.cpp"
+       .globl  _Z1fv                   # -- Begin function _Z1fv
+       .p2align        4, 0x90
+       .type   _Z1fv,@function
+_Z1fv:                                  # @_Z1fv
+.Lfunc_begin0:
+       .file   1 "/tmp" "frame-types.cpp"
+       .loc    1 3 0                   # frame-types.cpp:3:0
+       .cfi_sections .debug_frame
+       .cfi_startproc
+# %bb.0:                                # %entry
+       pushl   %ebp
+       .cfi_def_cfa_offset 8
+       .cfi_offset %ebp, -8
+       movl    %esp, %ebp
+       .cfi_def_cfa_register %ebp
+       subl    $352, %esp              # imm = 0x160
+.Ltmp0:
+       .loc    1 6 9 prologue_end      # frame-types.cpp:6:9
+       leal    -1(%ebp), %eax
+.Ltmp1:
+       #DEBUG_VALUE: f:a <- [$eax+0]
+       movl    %eax, -12(%ebp)
+       .loc    1 7 14                  # frame-types.cpp:7:14
+       movb    $1, -17(%ebp)
+       .loc    1 7 10 is_stmt 0        # frame-types.cpp:7:10
+       leal    -17(%ebp), %eax
+.Ltmp2:
+       movl    %eax, -16(%ebp)
+       .loc    1 10 14 is_stmt 1       # frame-types.cpp:10:14
+       movb    $2, -37(%ebp)
+       .loc    1 17 1                  # frame-types.cpp:17:1
+       addl    $352, %esp              # imm = 0x160
+       popl    %ebp
+       .cfi_def_cfa %esp, 4
+       retl
+.Ltmp3:
+.Lfunc_end0:
+       .size   _Z1fv, .Lfunc_end0-_Z1fv
+       .cfi_endproc
+                                        # -- End function
+       .section        .debug_str,"MS",@progbits,1
+.Linfo_string0:
+       .asciz  "clang version 9.0.0 "  # string offset=0
+.Linfo_string1:
+       .asciz  "frame-types.cpp"       # string offset=21
+.Linfo_string2:
+       .asciz  "/tmp"                  # string offset=37
+.Linfo_string3:
+       .asciz  "_Z1fv"                 # string offset=42
+.Linfo_string4:
+       .asciz  "f"                     # string offset=48
+.Linfo_string5:
+       .asciz  "a"                     # string offset=50
+.Linfo_string6:
+       .asciz  "char"                  # string offset=52
+.Linfo_string7:
+       .asciz  "b"                     # string offset=57
+.Linfo_string8:
+       .asciz  "c"                     # string offset=59
+.Linfo_string9:
+       .asciz  "d"                     # string offset=61
+.Linfo_string10:
+       .asciz  "e"                     # string offset=63
+.Linfo_string11:
+       .asciz  "S"                     # string offset=65
+.Linfo_string12:
+       .asciz  "g"                     # string offset=67
+.Linfo_string13:
+       .asciz  "h"                     # string offset=69
+.Linfo_string14:
+       .asciz  "i"                     # string offset=71
+.Linfo_string15:
+       .asciz  "j"                     # string offset=73
+.Linfo_string16:
+       .asciz  "char_typedef"          # string offset=75
+.Linfo_string17:
+       .asciz  "k"                     # string offset=88
+.Linfo_string18:
+       .asciz  "__ARRAY_SIZE_TYPE__"   # string offset=90
+.Linfo_string19:
+       .asciz  "l"                     # string offset=110
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                       # Abbreviation Code
+       .byte   17                      # DW_TAG_compile_unit
+       .byte   1                       # DW_CHILDREN_yes
+       .byte   37                      # DW_AT_producer
+       .byte   14                      # DW_FORM_strp
+       .byte   19                      # DW_AT_language
+       .byte   5                       # DW_FORM_data2
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   16                      # DW_AT_stmt_list
+       .byte   23                      # DW_FORM_sec_offset
+       .byte   27                      # DW_AT_comp_dir
+       .byte   14                      # DW_FORM_strp
+       .byte   17                      # DW_AT_low_pc
+       .byte   1                       # DW_FORM_addr
+       .byte   18                      # DW_AT_high_pc
+       .byte   6                       # DW_FORM_data4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   2                       # Abbreviation Code
+       .byte   46                      # DW_TAG_subprogram
+       .byte   1                       # DW_CHILDREN_yes
+       .byte   17                      # DW_AT_low_pc
+       .byte   1                       # DW_FORM_addr
+       .byte   18                      # DW_AT_high_pc
+       .byte   6                       # DW_FORM_data4
+       .byte   64                      # DW_AT_frame_base
+       .byte   24                      # DW_FORM_exprloc
+       .byte   110                     # DW_AT_linkage_name
+       .byte   14                      # DW_FORM_strp
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   63                      # DW_AT_external
+       .byte   25                      # DW_FORM_flag_present
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   3                       # Abbreviation Code
+       .byte   52                      # DW_TAG_variable
+       .byte   0                       # DW_CHILDREN_no
+       .byte   2                       # DW_AT_location
+       .byte   24                      # DW_FORM_exprloc
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   4                       # Abbreviation Code
+       .byte   22                      # DW_TAG_typedef
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   5                       # Abbreviation Code
+       .byte   36                      # DW_TAG_base_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   62                      # DW_AT_encoding
+       .byte   11                      # DW_FORM_data1
+       .byte   11                      # DW_AT_byte_size
+       .byte   11                      # DW_FORM_data1
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   6                       # Abbreviation Code
+       .byte   15                      # DW_TAG_pointer_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   7                       # Abbreviation Code
+       .byte   16                      # DW_TAG_reference_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   8                       # Abbreviation Code
+       .byte   66                      # DW_TAG_rvalue_reference_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   9                       # Abbreviation Code
+       .byte   31                      # DW_TAG_ptr_to_member_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   29                      # DW_AT_containing_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   10                      # Abbreviation Code
+       .byte   21                      # DW_TAG_subroutine_type
+       .byte   1                       # DW_CHILDREN_yes
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   11                      # Abbreviation Code
+       .byte   5                       # DW_TAG_formal_parameter
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   52                      # DW_AT_artificial
+       .byte   25                      # DW_FORM_flag_present
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   12                      # Abbreviation Code
+       .byte   19                      # DW_TAG_structure_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   60                      # DW_AT_declaration
+       .byte   25                      # DW_FORM_flag_present
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   13                      # Abbreviation Code
+       .byte   38                      # DW_TAG_const_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   14                      # Abbreviation Code
+       .byte   53                      # DW_TAG_volatile_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   15                      # Abbreviation Code
+       .byte   55                      # DW_TAG_restrict_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   16                      # Abbreviation Code
+       .byte   1                       # DW_TAG_array_type
+       .byte   1                       # DW_CHILDREN_yes
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   17                      # Abbreviation Code
+       .byte   33                      # DW_TAG_subrange_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   55                      # DW_AT_count
+       .byte   11                      # DW_FORM_data1
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   18                      # Abbreviation Code
+       .byte   36                      # DW_TAG_base_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   11                      # DW_AT_byte_size
+       .byte   11                      # DW_FORM_data1
+       .byte   62                      # DW_AT_encoding
+       .byte   11                      # DW_FORM_data1
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   0                       # EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+       .short  4                       # DWARF version number
+       .long   .debug_abbrev           # Offset Into Abbrev. Section
+       .byte   4                       # Address Size (in bytes)
+       .byte   1                       # Abbrev [1] 0xb:0x157 DW_TAG_compile_unit
+       .long   .Linfo_string0          # DW_AT_producer
+       .short  4                       # DW_AT_language
+       .long   .Linfo_string1          # DW_AT_name
+       .long   .Lline_table_start0     # DW_AT_stmt_list
+       .long   .Linfo_string2          # DW_AT_comp_dir
+       .long   .Lfunc_begin0           # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+       .byte   2                       # Abbrev [2] 0x26:0xca DW_TAG_subprogram
+       .long   .Lfunc_begin0           # DW_AT_low_pc
+       .long   .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
+       .byte   1                       # DW_AT_frame_base
+       .byte   85
+       .long   .Linfo_string3          # DW_AT_linkage_name
+       .long   .Linfo_string4          # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   3                       # DW_AT_decl_line
+                                        # DW_AT_external
+       .byte   3                       # Abbrev [3] 0x3b:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   127
+       .long   .Linfo_string5          # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   4                       # DW_AT_decl_line
+       .long   240                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x49:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   120
+       .long   .Linfo_string7          # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   5                       # DW_AT_decl_line
+       .long   247                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x57:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   116
+       .long   .Linfo_string8          # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   6                       # DW_AT_decl_line
+       .long   252                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x65:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   112
+       .long   .Linfo_string9          # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   7                       # DW_AT_decl_line
+       .long   257                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x73:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   96
+       .long   .Linfo_string10         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   8                       # DW_AT_decl_line
+       .long   262                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x81:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   92
+       .long   .Linfo_string4          # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   9                       # DW_AT_decl_line
+       .long   292                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x8f:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   91
+       .long   .Linfo_string12         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   10                      # DW_AT_decl_line
+       .long   301                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0x9d:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   90
+       .long   .Linfo_string13         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   11                      # DW_AT_decl_line
+       .long   306                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0xab:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   84
+       .long   .Linfo_string14         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   12                      # DW_AT_decl_line
+       .long   311                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0xb9:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   83
+       .long   .Linfo_string15         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   14                      # DW_AT_decl_line
+       .long   228                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0xc7:0xe DW_TAG_variable
+       .byte   2                       # DW_AT_location
+       .byte   145
+       .byte   71
+       .long   .Linfo_string17         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   15                      # DW_AT_decl_line
+       .long   316                     # DW_AT_type
+       .byte   3                       # Abbrev [3] 0xd5:0xf DW_TAG_variable
+       .byte   3                       # DW_AT_location
+       .byte   145
+       .ascii  "\247}"
+       .long   .Linfo_string19         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   16                      # DW_AT_decl_line
+       .long   335                     # DW_AT_type
+       .byte   4                       # Abbrev [4] 0xe4:0xb DW_TAG_typedef
+       .long   240                     # DW_AT_type
+       .long   .Linfo_string16         # DW_AT_name
+       .byte   1                       # DW_AT_decl_file
+       .byte   13                      # DW_AT_decl_line
+       .byte   0                       # End Of Children Mark
+       .byte   5                       # Abbrev [5] 0xf0:0x7 DW_TAG_base_type
+       .long   .Linfo_string6          # DW_AT_name
+       .byte   6                       # DW_AT_encoding
+       .byte   1                       # DW_AT_byte_size
+       .byte   6                       # Abbrev [6] 0xf7:0x5 DW_TAG_pointer_type
+       .long   240                     # DW_AT_type
+       .byte   7                       # Abbrev [7] 0xfc:0x5 DW_TAG_reference_type
+       .long   240                     # DW_AT_type
+       .byte   8                       # Abbrev [8] 0x101:0x5 DW_TAG_rvalue_reference_type
+       .long   240                     # DW_AT_type
+       .byte   9                       # Abbrev [9] 0x106:0x9 DW_TAG_ptr_to_member_type
+       .long   271                     # DW_AT_type
+       .long   287                     # DW_AT_containing_type
+       .byte   10                      # Abbrev [10] 0x10f:0xb DW_TAG_subroutine_type
+       .long   240                     # DW_AT_type
+       .byte   11                      # Abbrev [11] 0x114:0x5 DW_TAG_formal_parameter
+       .long   282                     # DW_AT_type
+                                        # DW_AT_artificial
+       .byte   0                       # End Of Children Mark
+       .byte   6                       # Abbrev [6] 0x11a:0x5 DW_TAG_pointer_type
+       .long   287                     # DW_AT_type
+       .byte   12                      # Abbrev [12] 0x11f:0x5 DW_TAG_structure_type
+       .long   .Linfo_string11         # DW_AT_name
+                                        # DW_AT_declaration
+       .byte   9                       # Abbrev [9] 0x124:0x9 DW_TAG_ptr_to_member_type
+       .long   240                     # DW_AT_type
+       .long   287                     # DW_AT_containing_type
+       .byte   13                      # Abbrev [13] 0x12d:0x5 DW_TAG_const_type
+       .long   240                     # DW_AT_type
+       .byte   14                      # Abbrev [14] 0x132:0x5 DW_TAG_volatile_type
+       .long   240                     # DW_AT_type
+       .byte   15                      # Abbrev [15] 0x137:0x5 DW_TAG_restrict_type
+       .long   247                     # DW_AT_type
+       .byte   16                      # Abbrev [16] 0x13c:0xc DW_TAG_array_type
+       .long   240                     # DW_AT_type
+       .byte   17                      # Abbrev [17] 0x141:0x6 DW_TAG_subrange_type
+       .long   328                     # DW_AT_type
+       .byte   12                      # DW_AT_count
+       .byte   0                       # End Of Children Mark
+       .byte   18                      # Abbrev [18] 0x148:0x7 DW_TAG_base_type
+       .long   .Linfo_string18         # DW_AT_name
+       .byte   8                       # DW_AT_byte_size
+       .byte   7                       # DW_AT_encoding
+       .byte   16                      # Abbrev [16] 0x14f:0x12 DW_TAG_array_type
+       .long   240                     # DW_AT_type
+       .byte   17                      # Abbrev [17] 0x154:0x6 DW_TAG_subrange_type
+       .long   328                     # DW_AT_type
+       .byte   12                      # DW_AT_count
+       .byte   17                      # Abbrev [17] 0x15a:0x6 DW_TAG_subrange_type
+       .long   328                     # DW_AT_type
+       .byte   24                      # DW_AT_count
+       .byte   0                       # End Of Children Mark
+       .byte   0                       # End Of Children Mark
+.Ldebug_info_end0:
+       .section        .debug_macinfo,"",@progbits
+       .byte   0                       # End Of Macro List Mark
+
+       .ident  "clang version 9.0.0 "
+       .section        ".note.GNU-stack","",@progbits
+       .addrsig
+       .section        .debug_line,"",@progbits
+.Lline_table_start0:
diff --git a/test/tools/llvm-symbolizer/frame.s b/test/tools/llvm-symbolizer/frame.s
new file mode 100644 (file)
index 0000000..70ede89
--- /dev/null
@@ -0,0 +1,687 @@
+// REQUIRES: aarch64-registered-target
+
+// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android -o %t.o %s
+// RUN: echo 'FRAME %t.o 0' | llvm-symbolizer | FileCheck %s
+
+// CHECK: f
+// CHECK-NEXT: a
+// CHECK-NEXT: /tmp/stack.c:20
+// CHECK-NEXT: -192 32 192
+// CHECK-NEXT: g
+// CHECK-NEXT: p
+// CHECK-NEXT: /tmp/stack.c:8
+// CHECK-NEXT: ?? 8 ??
+// CHECK-NEXT: g
+// CHECK-NEXT: b
+// CHECK-NEXT: /tmp/stack.c:10
+// CHECK-NEXT: -128 32 128
+// CHECK-NEXT: h
+// CHECK-NEXT: p1
+// CHECK-NEXT: /tmp/stack.c:3
+// CHECK-NEXT: ?? 8 ??
+// CHECK-NEXT: h
+// CHECK-NEXT: p2
+// CHECK-NEXT: /tmp/stack.c:3
+// CHECK-NEXT: ?? 8 ??
+// CHECK-NEXT: h
+// CHECK-NEXT: d
+// CHECK-NEXT: /tmp/stack.c:4
+// CHECK-NEXT: -96 32 0
+// CHECK-NEXT: g
+// CHECK-NEXT: c
+// CHECK-NEXT: /tmp/stack.c:14
+// CHECK-NEXT: -160 32 64
+// CHECK-NEXT: h
+// CHECK-NEXT: p1
+// CHECK-NEXT: /tmp/stack.c:3
+// CHECK-NEXT: ?? 8 ??
+// CHECK-NEXT: h
+// CHECK-NEXT: p2
+// CHECK-NEXT: /tmp/stack.c:3
+// CHECK-NEXT: ?? 8 ??
+// CHECK-NEXT: h
+// CHECK-NEXT: d
+// CHECK-NEXT: /tmp/stack.c:4
+// CHECK-NEXT: -96 32 0
+
+// Generated from:
+//
+// void i(void *, void *, void *);
+//
+// static void h(void *p1, void *p2) {
+//   char d[32];
+//   i(d, p1, p2);
+// }
+//
+// static void g(void *p) {
+//   {
+//     char b[32];
+//     h(b, p);
+//   }
+//   {
+//     char c[32];
+//     h(c, p);
+//   }
+// }
+//
+// clang -S -o - -fsanitize=hwaddress --target=aarch64-linux-android /tmp/stack.c -O -fsanitize-hwaddress-abi=platform -g
+
+       .text
+       .file   "stack.c"
+       .globl  f                       // -- Begin function f
+       .p2align        2
+       .type   f,@function
+f:                                      // @f
+.Lfunc_begin0:
+       .file   1 "/tmp" "stack.c"
+       .loc    1 19 0                  // stack.c:19:0
+       .cfi_startproc
+// %bb.0:                               // %entry
+       sub     sp, sp, #208            // =208
+       stp     x26, x25, [sp, #128]    // 16-byte Folded Spill
+       stp     x24, x23, [sp, #144]    // 16-byte Folded Spill
+       stp     x22, x21, [sp, #160]    // 16-byte Folded Spill
+       stp     x20, x19, [sp, #176]    // 16-byte Folded Spill
+       stp     x29, x30, [sp, #192]    // 16-byte Folded Spill
+       add     x29, sp, #192           // =192
+       .cfi_def_cfa w29, 16
+       .cfi_offset w30, -8
+       .cfi_offset w29, -16
+       .cfi_offset w19, -24
+       .cfi_offset w20, -32
+       .cfi_offset w21, -40
+       .cfi_offset w22, -48
+       .cfi_offset w23, -56
+       .cfi_offset w24, -64
+       .cfi_offset w25, -72
+       .cfi_offset w26, -80
+       mrs     x8, TPIDR_EL0
+       ldr     x12, [x8, #48]
+.Ltmp0:
+       adr     x14, .Ltmp0
+       orr     x14, x14, x29, lsl #44
+       add     x9, sp, #96             // =96
+       asr     x15, x12, #3
+       asr     x16, x12, #56
+       orr     x17, x12, #0xffffffff
+       str     x14, [x12], #8
+       bic     x12, x12, x16, lsl #12
+       str     x12, [x8, #48]
+.Ltmp1:
+       .loc    1 4 8 prologue_end      // stack.c:4:8
+       and     w8, w15, #0xff
+       lsr     x22, x9, #4
+       add     x25, x17, #1            // =1
+       bfi     w8, w8, #8, #8
+       add     x10, sp, #64            // =64
+       strh    w8, [x25, x22]
+.Ltmp2:
+       .loc    1 10 10                 // stack.c:10:10
+       eor     x8, x15, #0x80
+       orr     x1, x10, x8, lsl #56
+       and     w8, w8, #0xff
+       lsr     x23, x10, #4
+       bfi     w8, w8, #8, #8
+       add     x11, sp, #32            // =32
+       strh    w8, [x25, x23]
+.Ltmp3:
+       .loc    1 14 10                 // stack.c:14:10
+       eor     x8, x15, #0x40
+       orr     x19, x11, x8, lsl #56
+       and     w8, w8, #0xff
+       lsr     x24, x11, #4
+       bfi     w8, w8, #8, #8
+       mov     x13, sp
+       strh    w8, [x25, x24]
+.Ltmp4:
+       .loc    1 20 3                  // stack.c:20:3
+       eor     x8, x15, #0xc0
+.Ltmp5:
+       .loc    1 4 8                   // stack.c:4:8
+       orr     x20, x9, x15, lsl #56
+.Ltmp6:
+       .loc    1 20 3                  // stack.c:20:3
+       orr     x21, x13, x8, lsl #56
+       and     w8, w8, #0xff
+       lsr     x26, x13, #4
+       bfi     w8, w8, #8, #8
+.Ltmp7:
+       .loc    1 5 3                   // stack.c:5:3
+       mov     x0, x20
+       mov     x2, x21
+.Ltmp8:
+       .loc    1 20 3                  // stack.c:20:3
+       strh    w8, [x25, x26]
+.Ltmp9:
+       //DEBUG_VALUE: h:p1 <- $x1
+       //DEBUG_VALUE: g:p <- $x21
+       //DEBUG_VALUE: h:p2 <- $x21
+       //DEBUG_VALUE: h:p2 <- $x21
+       .loc    1 5 3                   // stack.c:5:3
+       bl      i
+.Ltmp10:
+       //DEBUG_VALUE: h:p1 <- $x19
+       .loc    1 5 3 is_stmt 0         // stack.c:5:3
+       mov     x0, x20
+       mov     x1, x19
+       mov     x2, x21
+       bl      i
+.Ltmp11:
+       .loc    1 22 1 is_stmt 1        // stack.c:22:1
+       strh    wzr, [x25, x22]
+       strh    wzr, [x25, x23]
+       strh    wzr, [x25, x24]
+       strh    wzr, [x25, x26]
+       ldp     x29, x30, [sp, #192]    // 16-byte Folded Reload
+       ldp     x20, x19, [sp, #176]    // 16-byte Folded Reload
+.Ltmp12:
+       ldp     x22, x21, [sp, #160]    // 16-byte Folded Reload
+.Ltmp13:
+       ldp     x24, x23, [sp, #144]    // 16-byte Folded Reload
+       ldp     x26, x25, [sp, #128]    // 16-byte Folded Reload
+       add     sp, sp, #208            // =208
+       ret
+.Ltmp14:
+.Lfunc_end0:
+       .size   f, .Lfunc_end0-f
+       .cfi_endproc
+                                        // -- End function
+       .section        .text.hwasan.module_ctor,"axG",@progbits,hwasan.module_ctor,comdat
+       .p2align        2               // -- Begin function hwasan.module_ctor
+       .type   hwasan.module_ctor,@function
+hwasan.module_ctor:                     // @hwasan.module_ctor
+.Lfunc_begin1:
+       .cfi_startproc
+// %bb.0:
+       str     x30, [sp, #-16]!        // 8-byte Folded Spill
+       .cfi_def_cfa_offset 16
+       .cfi_offset w30, -16
+       bl      __hwasan_init
+       ldr     x30, [sp], #16          // 8-byte Folded Reload
+       ret
+.Lfunc_end1:
+       .size   hwasan.module_ctor, .Lfunc_end1-hwasan.module_ctor
+       .cfi_endproc
+                                        // -- End function
+       .section        .init_array.0,"aGw",@init_array,hwasan.module_ctor,comdat
+       .p2align        3
+       .xword  hwasan.module_ctor
+       .section        .debug_str,"MS",@progbits,1
+.Linfo_string0:
+       .asciz  "clang version 9.0.0 "  // string offset=0
+.Linfo_string1:
+       .asciz  "stack.c"               // string offset=21
+.Linfo_string2:
+       .asciz  "/tmp"                  // string offset=29
+.Linfo_string3:
+       .asciz  "h"                     // string offset=34
+.Linfo_string4:
+       .asciz  "p1"                    // string offset=36
+.Linfo_string5:
+       .asciz  "p2"                    // string offset=39
+.Linfo_string6:
+       .asciz  "d"                     // string offset=42
+.Linfo_string7:
+       .asciz  "char"                  // string offset=44
+.Linfo_string8:
+       .asciz  "__ARRAY_SIZE_TYPE__"   // string offset=49
+.Linfo_string9:
+       .asciz  "g"                     // string offset=69
+.Linfo_string10:
+       .asciz  "p"                     // string offset=71
+.Linfo_string11:
+       .asciz  "b"                     // string offset=73
+.Linfo_string12:
+       .asciz  "c"                     // string offset=75
+.Linfo_string13:
+       .asciz  "f"                     // string offset=77
+.Linfo_string14:
+       .asciz  "a"                     // string offset=79
+       .section        .debug_loc,"",@progbits
+.Ldebug_loc0:
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp10-.Lfunc_begin0
+       .hword  1                       // Loc expr size
+       .byte   81                      // DW_OP_reg1
+       .xword  0
+       .xword  0
+.Ldebug_loc1:
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp13-.Lfunc_begin0
+       .hword  1                       // Loc expr size
+       .byte   101                     // DW_OP_reg21
+       .xword  0
+       .xword  0
+.Ldebug_loc2:
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp13-.Lfunc_begin0
+       .hword  1                       // Loc expr size
+       .byte   101                     // DW_OP_reg21
+       .xword  0
+       .xword  0
+.Ldebug_loc3:
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp13-.Lfunc_begin0
+       .hword  1                       // Loc expr size
+       .byte   101                     // DW_OP_reg21
+       .xword  0
+       .xword  0
+.Ldebug_loc4:
+       .xword  .Ltmp10-.Lfunc_begin0
+       .xword  .Ltmp12-.Lfunc_begin0
+       .hword  1                       // Loc expr size
+       .byte   99                      // DW_OP_reg19
+       .xword  0
+       .xword  0
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                       // Abbreviation Code
+       .byte   17                      // DW_TAG_compile_unit
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   37                      // DW_AT_producer
+       .byte   14                      // DW_FORM_strp
+       .byte   19                      // DW_AT_language
+       .byte   5                       // DW_FORM_data2
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   16                      // DW_AT_stmt_list
+       .byte   23                      // DW_FORM_sec_offset
+       .byte   27                      // DW_AT_comp_dir
+       .byte   14                      // DW_FORM_strp
+       .byte   17                      // DW_AT_low_pc
+       .byte   1                       // DW_FORM_addr
+       .byte   18                      // DW_AT_high_pc
+       .byte   6                       // DW_FORM_data4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   2                       // Abbreviation Code
+       .byte   46                      // DW_TAG_subprogram
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   58                      // DW_AT_decl_file
+       .byte   11                      // DW_FORM_data1
+       .byte   59                      // DW_AT_decl_line
+       .byte   11                      // DW_FORM_data1
+       .byte   39                      // DW_AT_prototyped
+       .byte   25                      // DW_FORM_flag_present
+       .byte   32                      // DW_AT_inline
+       .byte   11                      // DW_FORM_data1
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   3                       // Abbreviation Code
+       .byte   5                       // DW_TAG_formal_parameter
+       .byte   0                       // DW_CHILDREN_no
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   58                      // DW_AT_decl_file
+       .byte   11                      // DW_FORM_data1
+       .byte   59                      // DW_AT_decl_line
+       .byte   11                      // DW_FORM_data1
+       .byte   73                      // DW_AT_type
+       .byte   19                      // DW_FORM_ref4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   4                       // Abbreviation Code
+       .byte   52                      // DW_TAG_variable
+       .byte   0                       // DW_CHILDREN_no
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   58                      // DW_AT_decl_file
+       .byte   11                      // DW_FORM_data1
+       .byte   59                      // DW_AT_decl_line
+       .byte   11                      // DW_FORM_data1
+       .byte   73                      // DW_AT_type
+       .byte   19                      // DW_FORM_ref4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   5                       // Abbreviation Code
+       .byte   15                      // DW_TAG_pointer_type
+       .byte   0                       // DW_CHILDREN_no
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   6                       // Abbreviation Code
+       .byte   1                       // DW_TAG_array_type
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   73                      // DW_AT_type
+       .byte   19                      // DW_FORM_ref4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   7                       // Abbreviation Code
+       .byte   33                      // DW_TAG_subrange_type
+       .byte   0                       // DW_CHILDREN_no
+       .byte   73                      // DW_AT_type
+       .byte   19                      // DW_FORM_ref4
+       .byte   55                      // DW_AT_count
+       .byte   11                      // DW_FORM_data1
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   8                       // Abbreviation Code
+       .byte   36                      // DW_TAG_base_type
+       .byte   0                       // DW_CHILDREN_no
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   62                      // DW_AT_encoding
+       .byte   11                      // DW_FORM_data1
+       .byte   11                      // DW_AT_byte_size
+       .byte   11                      // DW_FORM_data1
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   9                       // Abbreviation Code
+       .byte   36                      // DW_TAG_base_type
+       .byte   0                       // DW_CHILDREN_no
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   11                      // DW_AT_byte_size
+       .byte   11                      // DW_FORM_data1
+       .byte   62                      // DW_AT_encoding
+       .byte   11                      // DW_FORM_data1
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   10                      // Abbreviation Code
+       .byte   11                      // DW_TAG_lexical_block
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   11                      // Abbreviation Code
+       .byte   46                      // DW_TAG_subprogram
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   17                      // DW_AT_low_pc
+       .byte   1                       // DW_FORM_addr
+       .byte   18                      // DW_AT_high_pc
+       .byte   6                       // DW_FORM_data4
+       .byte   64                      // DW_AT_frame_base
+       .byte   24                      // DW_FORM_exprloc
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   58                      // DW_AT_decl_file
+       .byte   11                      // DW_FORM_data1
+       .byte   59                      // DW_AT_decl_line
+       .byte   11                      // DW_FORM_data1
+       .byte   63                      // DW_AT_external
+       .byte   25                      // DW_FORM_flag_present
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   12                      // Abbreviation Code
+       .byte   52                      // DW_TAG_variable
+       .byte   0                       // DW_CHILDREN_no
+       .byte   2                       // DW_AT_location
+       .byte   24                      // DW_FORM_exprloc
+       .ascii  "\203|"                 // DW_AT_LLVM_tag_offset
+       .byte   11                      // DW_FORM_data1
+       .byte   3                       // DW_AT_name
+       .byte   14                      // DW_FORM_strp
+       .byte   58                      // DW_AT_decl_file
+       .byte   11                      // DW_FORM_data1
+       .byte   59                      // DW_AT_decl_line
+       .byte   11                      // DW_FORM_data1
+       .byte   73                      // DW_AT_type
+       .byte   19                      // DW_FORM_ref4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   13                      // Abbreviation Code
+       .byte   29                      // DW_TAG_inlined_subroutine
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   49                      // DW_AT_abstract_origin
+       .byte   19                      // DW_FORM_ref4
+       .byte   85                      // DW_AT_ranges
+       .byte   23                      // DW_FORM_sec_offset
+       .byte   88                      // DW_AT_call_file
+       .byte   11                      // DW_FORM_data1
+       .byte   89                      // DW_AT_call_line
+       .byte   11                      // DW_FORM_data1
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   14                      // Abbreviation Code
+       .byte   5                       // DW_TAG_formal_parameter
+       .byte   0                       // DW_CHILDREN_no
+       .byte   2                       // DW_AT_location
+       .byte   23                      // DW_FORM_sec_offset
+       .byte   49                      // DW_AT_abstract_origin
+       .byte   19                      // DW_FORM_ref4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   15                      // Abbreviation Code
+       .byte   11                      // DW_TAG_lexical_block
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   85                      // DW_AT_ranges
+       .byte   23                      // DW_FORM_sec_offset
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   16                      // Abbreviation Code
+       .byte   52                      // DW_TAG_variable
+       .byte   0                       // DW_CHILDREN_no
+       .byte   2                       // DW_AT_location
+       .byte   24                      // DW_FORM_exprloc
+       .ascii  "\203|"                 // DW_AT_LLVM_tag_offset
+       .byte   11                      // DW_FORM_data1
+       .byte   49                      // DW_AT_abstract_origin
+       .byte   19                      // DW_FORM_ref4
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   17                      // Abbreviation Code
+       .byte   29                      // DW_TAG_inlined_subroutine
+       .byte   1                       // DW_CHILDREN_yes
+       .byte   49                      // DW_AT_abstract_origin
+       .byte   19                      // DW_FORM_ref4
+       .byte   17                      // DW_AT_low_pc
+       .byte   1                       // DW_FORM_addr
+       .byte   18                      // DW_AT_high_pc
+       .byte   6                       // DW_FORM_data4
+       .byte   88                      // DW_AT_call_file
+       .byte   11                      // DW_FORM_data1
+       .byte   89                      // DW_AT_call_line
+       .byte   11                      // DW_FORM_data1
+       .byte   0                       // EOM(1)
+       .byte   0                       // EOM(2)
+       .byte   0                       // EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .word   .Ldebug_info_end0-.Ldebug_info_start0 // Length of Unit
+.Ldebug_info_start0:
+       .hword  4                       // DWARF version number
+       .word   .debug_abbrev           // Offset Into Abbrev. Section
+       .byte   8                       // Address Size (in bytes)
+       .byte   1                       // Abbrev [1] 0xb:0x146 DW_TAG_compile_unit
+       .word   .Linfo_string0          // DW_AT_producer
+       .hword  12                      // DW_AT_language
+       .word   .Linfo_string1          // DW_AT_name
+       .word   .Lline_table_start0     // DW_AT_stmt_list
+       .word   .Linfo_string2          // DW_AT_comp_dir
+       .xword  .Lfunc_begin0           // DW_AT_low_pc
+       .word   .Lfunc_end0-.Lfunc_begin0 // DW_AT_high_pc
+       .byte   2                       // Abbrev [2] 0x2a:0x2a DW_TAG_subprogram
+       .word   .Linfo_string3          // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   3                       // DW_AT_decl_line
+                                        // DW_AT_prototyped
+       .byte   1                       // DW_AT_inline
+       .byte   3                       // Abbrev [3] 0x32:0xb DW_TAG_formal_parameter
+       .word   .Linfo_string4          // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   3                       // DW_AT_decl_line
+       .word   84                      // DW_AT_type
+       .byte   3                       // Abbrev [3] 0x3d:0xb DW_TAG_formal_parameter
+       .word   .Linfo_string5          // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   3                       // DW_AT_decl_line
+       .word   84                      // DW_AT_type
+       .byte   4                       // Abbrev [4] 0x48:0xb DW_TAG_variable
+       .word   .Linfo_string6          // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   4                       // DW_AT_decl_line
+       .word   85                      // DW_AT_type
+       .byte   0                       // End Of Children Mark
+       .byte   5                       // Abbrev [5] 0x54:0x1 DW_TAG_pointer_type
+       .byte   6                       // Abbrev [6] 0x55:0xc DW_TAG_array_type
+       .word   97                      // DW_AT_type
+       .byte   7                       // Abbrev [7] 0x5a:0x6 DW_TAG_subrange_type
+       .word   104                     // DW_AT_type
+       .byte   32                      // DW_AT_count
+       .byte   0                       // End Of Children Mark
+       .byte   8                       // Abbrev [8] 0x61:0x7 DW_TAG_base_type
+       .word   .Linfo_string7          // DW_AT_name
+       .byte   8                       // DW_AT_encoding
+       .byte   1                       // DW_AT_byte_size
+       .byte   9                       // Abbrev [9] 0x68:0x7 DW_TAG_base_type
+       .word   .Linfo_string8          // DW_AT_name
+       .byte   8                       // DW_AT_byte_size
+       .byte   7                       // DW_AT_encoding
+       .byte   2                       // Abbrev [2] 0x6f:0x2e DW_TAG_subprogram
+       .word   .Linfo_string9          // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   8                       // DW_AT_decl_line
+                                        // DW_AT_prototyped
+       .byte   1                       // DW_AT_inline
+       .byte   3                       // Abbrev [3] 0x77:0xb DW_TAG_formal_parameter
+       .word   .Linfo_string10         // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   8                       // DW_AT_decl_line
+       .word   84                      // DW_AT_type
+       .byte   10                      // Abbrev [10] 0x82:0xd DW_TAG_lexical_block
+       .byte   4                       // Abbrev [4] 0x83:0xb DW_TAG_variable
+       .word   .Linfo_string11         // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   10                      // DW_AT_decl_line
+       .word   85                      // DW_AT_type
+       .byte   0                       // End Of Children Mark
+       .byte   10                      // Abbrev [10] 0x8f:0xd DW_TAG_lexical_block
+       .byte   4                       // Abbrev [4] 0x90:0xb DW_TAG_variable
+       .word   .Linfo_string12         // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   14                      // DW_AT_decl_line
+       .word   85                      // DW_AT_type
+       .byte   0                       // End Of Children Mark
+       .byte   0                       // End Of Children Mark
+       .byte   11                      // Abbrev [11] 0x9d:0xb3 DW_TAG_subprogram
+       .xword  .Lfunc_begin0           // DW_AT_low_pc
+       .word   .Lfunc_end0-.Lfunc_begin0 // DW_AT_high_pc
+       .byte   1                       // DW_AT_frame_base
+       .byte   109
+       .word   .Linfo_string13         // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   19                      // DW_AT_decl_line
+                                        // DW_AT_external
+       .byte   12                      // Abbrev [12] 0xb2:0x10 DW_TAG_variable
+       .byte   3                       // DW_AT_location
+       .byte   145
+       .ascii  "\300~"
+       .byte   192                     // DW_AT_LLVM_tag_offset
+       .word   .Linfo_string14         // DW_AT_name
+       .byte   1                       // DW_AT_decl_file
+       .byte   20                      // DW_AT_decl_line
+       .word   85                      // DW_AT_type
+       .byte   13                      // Abbrev [13] 0xc2:0x8d DW_TAG_inlined_subroutine
+       .word   111                     // DW_AT_abstract_origin
+       .word   .Ldebug_ranges0         // DW_AT_ranges
+       .byte   1                       // DW_AT_call_file
+       .byte   21                      // DW_AT_call_line
+       .byte   14                      // Abbrev [14] 0xcd:0x9 DW_TAG_formal_parameter
+       .word   .Ldebug_loc1            // DW_AT_location
+       .word   119                     // DW_AT_abstract_origin
+       .byte   15                      // Abbrev [15] 0xd6:0x38 DW_TAG_lexical_block
+       .word   .Ldebug_ranges2         // DW_AT_ranges
+       .byte   16                      // Abbrev [16] 0xdb:0xa DW_TAG_variable
+       .byte   3                       // DW_AT_location
+       .byte   145
+       .ascii  "\200\177"
+       .byte   128                     // DW_AT_LLVM_tag_offset
+       .word   131                     // DW_AT_abstract_origin
+       .byte   13                      // Abbrev [13] 0xe5:0x28 DW_TAG_inlined_subroutine
+       .word   42                      // DW_AT_abstract_origin
+       .word   .Ldebug_ranges1         // DW_AT_ranges
+       .byte   1                       // DW_AT_call_file
+       .byte   11                      // DW_AT_call_line
+       .byte   14                      // Abbrev [14] 0xf0:0x9 DW_TAG_formal_parameter
+       .word   .Ldebug_loc0            // DW_AT_location
+       .word   50                      // DW_AT_abstract_origin
+       .byte   14                      // Abbrev [14] 0xf9:0x9 DW_TAG_formal_parameter
+       .word   .Ldebug_loc2            // DW_AT_location
+       .word   61                      // DW_AT_abstract_origin
+       .byte   16                      // Abbrev [16] 0x102:0xa DW_TAG_variable
+       .byte   3                       // DW_AT_location
+       .byte   145
+       .ascii  "\240\177"
+       .byte   0                       // DW_AT_LLVM_tag_offset
+       .word   72                      // DW_AT_abstract_origin
+       .byte   0                       // End Of Children Mark
+       .byte   0                       // End Of Children Mark
+       .byte   15                      // Abbrev [15] 0x10e:0x40 DW_TAG_lexical_block
+       .word   .Ldebug_ranges3         // DW_AT_ranges
+       .byte   16                      // Abbrev [16] 0x113:0xa DW_TAG_variable
+       .byte   3                       // DW_AT_location
+       .byte   145
+       .ascii  "\340~"
+       .byte   64                      // DW_AT_LLVM_tag_offset
+       .word   144                     // DW_AT_abstract_origin
+       .byte   17                      // Abbrev [17] 0x11d:0x30 DW_TAG_inlined_subroutine
+       .word   42                      // DW_AT_abstract_origin
+       .xword  .Ltmp10                 // DW_AT_low_pc
+       .word   .Ltmp11-.Ltmp10         // DW_AT_high_pc
+       .byte   1                       // DW_AT_call_file
+       .byte   15                      // DW_AT_call_line
+       .byte   14                      // Abbrev [14] 0x130:0x9 DW_TAG_formal_parameter
+       .word   .Ldebug_loc4            // DW_AT_location
+       .word   50                      // DW_AT_abstract_origin
+       .byte   14                      // Abbrev [14] 0x139:0x9 DW_TAG_formal_parameter
+       .word   .Ldebug_loc3            // DW_AT_location
+       .word   61                      // DW_AT_abstract_origin
+       .byte   16                      // Abbrev [16] 0x142:0xa DW_TAG_variable
+       .byte   3                       // DW_AT_location
+       .byte   145
+       .ascii  "\240\177"
+       .byte   0                       // DW_AT_LLVM_tag_offset
+       .word   72                      // DW_AT_abstract_origin
+       .byte   0                       // End Of Children Mark
+       .byte   0                       // End Of Children Mark
+       .byte   0                       // End Of Children Mark
+       .byte   0                       // End Of Children Mark
+       .byte   0                       // End Of Children Mark
+.Ldebug_info_end0:
+       .section        .debug_ranges,"",@progbits
+.Ldebug_ranges0:
+       .xword  .Ltmp1-.Lfunc_begin0
+       .xword  .Ltmp4-.Lfunc_begin0
+       .xword  .Ltmp5-.Lfunc_begin0
+       .xword  .Ltmp6-.Lfunc_begin0
+       .xword  .Ltmp7-.Lfunc_begin0
+       .xword  .Ltmp8-.Lfunc_begin0
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp11-.Lfunc_begin0
+       .xword  0
+       .xword  0
+.Ldebug_ranges1:
+       .xword  .Ltmp1-.Lfunc_begin0
+       .xword  .Ltmp2-.Lfunc_begin0
+       .xword  .Ltmp5-.Lfunc_begin0
+       .xword  .Ltmp6-.Lfunc_begin0
+       .xword  .Ltmp7-.Lfunc_begin0
+       .xword  .Ltmp8-.Lfunc_begin0
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp10-.Lfunc_begin0
+       .xword  0
+       .xword  0
+.Ldebug_ranges2:
+       .xword  .Ltmp1-.Lfunc_begin0
+       .xword  .Ltmp3-.Lfunc_begin0
+       .xword  .Ltmp5-.Lfunc_begin0
+       .xword  .Ltmp6-.Lfunc_begin0
+       .xword  .Ltmp7-.Lfunc_begin0
+       .xword  .Ltmp8-.Lfunc_begin0
+       .xword  .Ltmp9-.Lfunc_begin0
+       .xword  .Ltmp10-.Lfunc_begin0
+       .xword  0
+       .xword  0
+.Ldebug_ranges3:
+       .xword  .Ltmp3-.Lfunc_begin0
+       .xword  .Ltmp4-.Lfunc_begin0
+       .xword  .Ltmp10-.Lfunc_begin0
+       .xword  .Ltmp11-.Lfunc_begin0
+       .xword  0
+       .xword  0
+       .section        .debug_macinfo,"",@progbits
+       .byte   0                       // End Of Macro List Mark
+
+       .ident  "clang version 9.0.0 "
+       .section        ".note.GNU-stack","",@progbits
+       .section        .debug_line,"",@progbits
+.Lline_table_start0:
index 61a94d6..ea94cf9 100644 (file)
@@ -166,17 +166,25 @@ static bool error(Expected<T> &ResOrErr) {
   return true;
 }
 
-static bool parseCommand(StringRef InputString, bool &IsData,
+enum class Command {
+  Code,
+  Data,
+  Frame,
+};
+
+static bool parseCommand(StringRef InputString, Command &Cmd,
                          std::string &ModuleName, uint64_t &ModuleOffset) {
   const char kDelimiters[] = " \n\r";
   ModuleName = "";
   if (InputString.consume_front("CODE ")) {
-    IsData = false;
+    Cmd = Command::Code;
   } else if (InputString.consume_front("DATA ")) {
-    IsData = true;
+    Cmd = Command::Data;
+  } else if (InputString.consume_front("FRAME ")) {
+    Cmd = Command::Frame;
   } else {
     // If no cmd, assume it's CODE.
-    IsData = false;
+    Cmd = Command::Code;
   }
   const char *pos = InputString.data();
   // Skip delimiters and parse input filename (if needed).
@@ -206,10 +214,10 @@ static bool parseCommand(StringRef InputString, bool &IsData,
 
 static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer,
                            DIPrinter &Printer) {
-  bool IsData = false;
+  Command Cmd;
   std::string ModuleName;
   uint64_t Offset = 0;
-  if (!parseCommand(StringRef(InputString), IsData, ModuleName, Offset)) {
+  if (!parseCommand(StringRef(InputString), Cmd, ModuleName, Offset)) {
     outs() << InputString;
     return;
   }
@@ -221,10 +229,19 @@ static void symbolizeInput(StringRef InputString, LLVMSymbolizer &Symbolizer,
     outs() << Delimiter;
   }
   Offset -= ClAdjustVMA;
-  if (IsData) {
+  if (Cmd == Command::Data) {
     auto ResOrErr = Symbolizer.symbolizeData(
         ModuleName, {Offset, object::SectionedAddress::UndefSection});
     Printer << (error(ResOrErr) ? DIGlobal() : ResOrErr.get());
+  } else if (Cmd == Command::Frame) {
+    auto ResOrErr = Symbolizer.symbolizeFrame(
+        ModuleName, {Offset, object::SectionedAddress::UndefSection});
+    if (!error(ResOrErr)) {
+      for (DILocal Local : *ResOrErr)
+        Printer << Local;
+      if (ResOrErr->empty())
+        outs() << "??\n";
+    }
   } else if (ClPrintInlining) {
     auto ResOrErr = Symbolizer.symbolizeInlinedCode(
         ModuleName, {Offset, object::SectionedAddress::UndefSection});