[llvm] r355148 - dsymutil support for DW_OP_convert

Adrian Prantl via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 28 14:12:32 PST 2019


Author: adrian
Date: Thu Feb 28 14:12:32 2019
New Revision: 355148

URL: http://llvm.org/viewvc/llvm-project?rev=355148&view=rev
Log:
dsymutil support for DW_OP_convert

Add support for cloning DWARF expressions that contain base type DIE
references in dsymutil.

<rdar://problem/48167812>

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

Added:
    llvm/trunk/test/tools/dsymutil/Inputs/op-convert.ll
    llvm/trunk/test/tools/dsymutil/Inputs/op-convert.macho.x86_64   (with props)
    llvm/trunk/test/tools/dsymutil/X86/op-convert.test
Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
    llvm/trunk/tools/dsymutil/DwarfLinker.cpp
    llvm/trunk/tools/dsymutil/DwarfLinker.h
    llvm/trunk/tools/dsymutil/DwarfStreamer.cpp
    llvm/trunk/tools/dsymutil/DwarfStreamer.h

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAttribute.h?rev=355148&r1=355147&r2=355148&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAttribute.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFAttribute.h Thu Feb 28 14:12:32 2019
@@ -42,6 +42,10 @@ struct DWARFAttribute {
     return isValid();
   }
 
+  /// Identifies DWARF attributes that may contain a reference to a
+  /// DWARF expression.
+  static bool mayHaveLocationDescription(dwarf::Attribute Attr);
+
   void clear() {
     Offset = 0;
     ByteSize = 0;

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=355148&r1=355147&r2=355148&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Thu Feb 28 14:12:32 2019
@@ -312,9 +312,7 @@ static void dumpAttribute(raw_ostream &O
       else
         FormValue.dump(OS, DumpOpts);
     }
-  } else if (Attr == DW_AT_location || Attr == DW_AT_frame_base ||
-             Attr == DW_AT_data_member_location ||
-             Attr == DW_AT_GNU_call_site_value)
+  } else if (DWARFAttribute::mayHaveLocationDescription(Attr))
     dumpLocation(OS, FormValue, U, sizeof(BaseIndent) + Indent + 4, DumpOpts);
   else
     FormValue.dump(OS, DumpOpts);
@@ -702,3 +700,39 @@ DWARFDie::attribute_iterator &DWARFDie::
     updateForIndex(*AbbrDecl, Index + 1);
   return *this;
 }
+
+bool DWARFAttribute::mayHaveLocationDescription(dwarf::Attribute Attr) {
+  switch (Attr) {
+  // From the DWARF v5 specification.
+  case DW_AT_location:
+  case DW_AT_byte_size:
+  case DW_AT_bit_size:
+  case DW_AT_string_length:
+  case DW_AT_lower_bound:
+  case DW_AT_return_addr:
+  case DW_AT_bit_stride:
+  case DW_AT_upper_bound:
+  case DW_AT_count:
+  case DW_AT_data_member_location:
+  case DW_AT_frame_base:
+  case DW_AT_segment:
+  case DW_AT_static_link:
+  case DW_AT_use_location:
+  case DW_AT_vtable_elem_location:
+  case DW_AT_allocated:
+  case DW_AT_associated:
+  case DW_AT_byte_stride:
+  case DW_AT_rank:
+  case DW_AT_call_value:
+  case DW_AT_call_origin:
+  case DW_AT_call_target:
+  case DW_AT_call_target_clobbered:
+  case DW_AT_call_data_location:
+  case DW_AT_call_data_value:
+  // Extensions.
+  case DW_AT_GNU_call_site_value:
+    return true;
+  default:
+    return false;
+  }
+}

Added: llvm/trunk/test/tools/dsymutil/Inputs/op-convert.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/op-convert.ll?rev=355148&view=auto
==============================================================================
--- llvm/trunk/test/tools/dsymutil/Inputs/op-convert.ll (added)
+++ llvm/trunk/test/tools/dsymutil/Inputs/op-convert.ll Thu Feb 28 14:12:32 2019
@@ -0,0 +1,45 @@
+; ModuleID = 'dbg.ll'
+source_filename = "dbg.c"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx"
+
+; Function Attrs: noinline nounwind uwtable
+define signext i8 @foo(i8 signext %x) #0 !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata i8 42, metadata !17, metadata !DIExpression(DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)), !dbg !12
+  call void @llvm.dbg.value(metadata i8 %x, metadata !11, metadata !DIExpression()), !dbg !12
+  call void @llvm.dbg.value(metadata i8 %x, metadata !13, metadata !DIExpression(DW_OP_LLVM_convert, 8, DW_ATE_signed, DW_OP_LLVM_convert, 32, DW_ATE_signed, DW_OP_stack_value)), !dbg !15
+  ret i8 %x, !dbg !16
+}
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #1
+
+attributes #0 = { noinline nounwind uwtable }
+attributes #1 = { nounwind readnone speculatable }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 9.0.0 (trunk 353791) (llvm/trunk 353801)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "dbg.c", directory: "/tmp", checksumkind: CSK_MD5, checksum: "2a034da6937f5b9cf6dd2d89127f57fd")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 9.0.0 (trunk 353791) (llvm/trunk 353801)"}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "signed char", size: 8, encoding: DW_ATE_signed_char)
+!11 = !DILocalVariable(name: "x", arg: 1, scope: !7, file: !1, line: 1, type: !10)
+!12 = !DILocation(line: 1, column: 29, scope: !7)
+!13 = !DILocalVariable(name: "y", scope: !7, file: !1, line: 3, type: !14)
+!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!15 = !DILocation(line: 3, column: 14, scope: !7)
+!16 = !DILocation(line: 4, column: 3, scope: !7)
+!17 = !DILocalVariable(name: "c", scope: !7, file: !1, line: 3, type: !14)

Added: llvm/trunk/test/tools/dsymutil/Inputs/op-convert.macho.x86_64
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/op-convert.macho.x86_64?rev=355148&view=auto
==============================================================================
Binary file - no diff available.

Propchange: llvm/trunk/test/tools/dsymutil/Inputs/op-convert.macho.x86_64
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: llvm/trunk/test/tools/dsymutil/X86/op-convert.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/op-convert.test?rev=355148&view=auto
==============================================================================
--- llvm/trunk/test/tools/dsymutil/X86/op-convert.test (added)
+++ llvm/trunk/test/tools/dsymutil/X86/op-convert.test Thu Feb 28 14:12:32 2019
@@ -0,0 +1,33 @@
+# REQUIRES: object-emission
+# RUN: dsymutil -f -o %t --verify -oso-prepend-path=%p/../Inputs -y %s
+# RUN: llvm-dwarfdump %t | FileCheck %s
+
+---
+triple:          'x86_64-apple-darwin'
+objects:
+  - filename: op-convert.macho.x86_64
+    symbols:
+      - { sym: _foo, objAddr: 0x0, binAddr: 0x1000, size: 0x4 }
+...
+
+
+CHECK:      DW_TAG_base_type
+CHECK-NEXT:     DW_AT_name	("DW_ATE_signed_8")
+CHECK-NEXT:     DW_AT_encoding	(DW_ATE_signed)
+CHECK-NEXT:     DW_AT_byte_size	(0x01)
+
+CHECK:   DW_TAG_base_type
+CHECK-NEXT:     DW_AT_name	("DW_ATE_signed_32")
+CHECK-NEXT:     DW_AT_encoding	(DW_ATE_signed)
+CHECK-NEXT:     DW_AT_byte_size	(0x04)
+
+CHECK:     DW_TAG_variable
+CHECK-NEXT:     DW_AT_location	(
+CHECK-NEXT:     [0x0000000000001000,  0x0000000000001002): DW_OP_breg5 RDI+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x0000002a) "DW_ATE_signed_8", DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value
+CHECK-NEXT:     [0x0000000000001002,  0x0000000000001003): DW_OP_breg0 RAX+0, DW_OP_constu 0xffffffff, DW_OP_and, DW_OP_convert (0x0000002a) "DW_ATE_signed_8", DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value)
+CHECK-NEXT:     DW_AT_name	("y")
+
+CHECK:     DW_TAG_variable
+CHECK-NEXT:     DW_AT_location	(DW_OP_constu 0x2a, DW_OP_convert (0x00000031) "DW_ATE_signed_32", DW_OP_stack_value)
+CHECK-NEXT:     DW_AT_name	("c")
+

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=355148&r1=355147&r2=355148&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Thu Feb 28 14:12:32 2019
@@ -125,7 +125,6 @@ static DWARFDie resolveDIEReference(cons
                                     CompileUnit *&RefCU) {
   assert(RefValue.isFormClass(DWARFFormValue::FC_Reference));
   uint64_t RefOffset = *RefValue.getAsReference();
-
   if ((RefCU = getUnitForOffset(Units, RefOffset)))
     if (const auto RefDie = RefCU->getOrigUnit().getDIEForOffset(RefOffset)) {
       // In a file with broken references, an attribute might point to a NULL
@@ -585,7 +584,7 @@ unsigned DwarfLinker::shouldKeepVariable
     MyInfo.InDebugMap = true;
     return Flags | TF_Keep;
   }
-
+  
   Optional<uint32_t> LocationIdx =
       Abbrev->findAttributeIndex(dwarf::DW_AT_location);
   if (!LocationIdx)
@@ -694,6 +693,9 @@ unsigned DwarfLinker::shouldKeepDIE(Relo
   case dwarf::DW_TAG_label:
     return shouldKeepSubprogramDIE(RelocMgr, Ranges, DIE, DMO, Unit, MyInfo,
                                    Flags);
+  case dwarf::DW_TAG_base_type:
+    // DWARF Expressions may reference basic types, but scanning them
+    // is expensive. Basic types are tiny, so just keep all of them.
   case dwarf::DW_TAG_imported_module:
   case dwarf::DW_TAG_imported_declaration:
   case dwarf::DW_TAG_imported_unit:
@@ -745,7 +747,6 @@ void DwarfLinker::keepDIEAndDependencies
   // Mark all DIEs referenced through attributes as kept.
   for (const auto &AttrSpec : Abbrev->attributes()) {
     DWARFFormValue Val(AttrSpec.Form);
-
     if (!Val.isFormClass(DWARFFormValue::FC_Reference) ||
         AttrSpec.Attr == dwarf::DW_AT_sibling) {
       DWARFFormValue::skipValue(AttrSpec.Form, Data, &Offset,
@@ -1052,15 +1053,74 @@ unsigned DwarfLinker::DIECloner::cloneDi
   return AttrSize;
 }
 
-unsigned DwarfLinker::DIECloner::cloneBlockAttribute(DIE &Die,
-                                                     AttributeSpec AttrSpec,
-                                                     const DWARFFormValue &Val,
-                                                     unsigned AttrSize) {
+void DwarfLinker::DIECloner::cloneExpression(
+    DataExtractor &Data, DWARFExpression Expression, const DebugMapObject &DMO,
+    CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer) {
+  using Encoding = DWARFExpression::Operation::Encoding;
+
+  uint32_t OpOffset = 0;
+  for (auto &Op : Expression) {
+    auto Description = Op.getDescription();
+    // DW_OP_const_type is variable-length and has 3
+    // operands. DWARFExpression thus far only supports 2.
+    auto Op0 = Description.Op[0];
+    auto Op1 = Description.Op[1];
+    if ((Op0 == Encoding::BaseTypeRef && Op1 != Encoding::SizeNA) ||
+        (Op1 == Encoding::BaseTypeRef && Op0 != Encoding::Size1))
+      Linker.reportWarning("Unsupported DW_OP encoding.", DMO);
+
+    if ((Op0 == Encoding::BaseTypeRef && Op1 == Encoding::SizeNA) ||
+        (Op1 == Encoding::BaseTypeRef && Op0 == Encoding::Size1)) {
+      // This code assumes that the other non-typeref operand fits into 1 byte.
+      assert(OpOffset < Op.getEndOffset());
+      uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
+      assert(ULEBsize <= 16);
+
+      // Copy over the operation.
+      OutputBuffer.push_back(Op.getCode());
+      uint64_t RefOffset;
+      if (Op1 == Encoding::SizeNA) {
+        RefOffset = Op.getRawOperand(0);
+      } else {
+        OutputBuffer.push_back(Op.getRawOperand(0));
+        RefOffset = Op.getRawOperand(1);
+      }
+      auto RefDie = Unit.getOrigUnit().getDIEForOffset(RefOffset);
+      uint32_t RefIdx = Unit.getOrigUnit().getDIEIndex(RefDie);
+      CompileUnit::DIEInfo &Info = Unit.getInfo(RefIdx);
+      uint32_t Offset = 0;
+      if (DIE *Clone = Info.Clone)
+        Offset = Clone->getOffset();
+      else
+        Linker.reportWarning("base type ref doesn't point to DW_TAG_base_type.",
+                             DMO);
+      uint8_t ULEB[16];
+      unsigned RealSize = encodeULEB128(Offset, ULEB, ULEBsize);
+      if (RealSize > ULEBsize) {
+        // Emit the generic type as a fallback.
+        RealSize = encodeULEB128(0, ULEB, ULEBsize);
+        Linker.reportWarning("base type ref doesn't fit.", DMO);
+      }
+      assert(RealSize == ULEBsize && "padding failed");
+      ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
+      OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
+    } else {
+      // Copy over everything else unmodified.
+      StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset());
+      OutputBuffer.append(Bytes.begin(), Bytes.end());
+    }
+    OpOffset = Op.getEndOffset();
+  }
+}
+
+unsigned DwarfLinker::DIECloner::cloneBlockAttribute(
+    DIE &Die, const DebugMapObject &DMO, CompileUnit &Unit,
+    AttributeSpec AttrSpec, const DWARFFormValue &Val, unsigned AttrSize,
+    bool IsLittleEndian) {
   DIEValueList *Attr;
   DIEValue Value;
   DIELoc *Loc = nullptr;
   DIEBlock *Block = nullptr;
-  // Just copy the block data over.
   if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
     Loc = new (DIEAlloc) DIELoc;
     Linker.DIELocs.push_back(Loc);
@@ -1077,10 +1137,26 @@ unsigned DwarfLinker::DIECloner::cloneBl
   else
     Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
                      dwarf::Form(AttrSpec.Form), Block);
+
+  // If the block is a DWARF Expression, clone it into the temporary
+  // buffer using cloneExpression(), otherwise copy the data directly.
+  SmallVector<uint8_t, 32> Buffer;
   ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
+  if (DWARFAttribute::mayHaveLocationDescription(AttrSpec.Attr) &&
+      (Val.isFormClass(DWARFFormValue::FC_Block) ||
+       Val.isFormClass(DWARFFormValue::FC_Exprloc))) {
+    DWARFUnit &OrigUnit = Unit.getOrigUnit();
+    DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
+                       IsLittleEndian, OrigUnit.getAddressByteSize());
+    DWARFExpression Expr(Data, OrigUnit.getVersion(),
+                         OrigUnit.getAddressByteSize());
+    cloneExpression(Data, Expr, DMO, Unit, Buffer);
+    Bytes = Buffer;
+  }
   for (auto Byte : Bytes)
     Attr->addValue(DIEAlloc, static_cast<dwarf::Attribute>(0),
                    dwarf::DW_FORM_data1, DIEInteger(Byte));
+
   // FIXME: If DIEBlock and DIELoc just reuses the Size field of
   // the DIE class, this if could be replaced by
   // Attr->setSize(Bytes.size()).
@@ -1198,8 +1274,9 @@ unsigned DwarfLinker::DIECloner::cloneSc
   // A more generic way to check for location attributes would be
   // nice, but it's very unlikely that any other attribute needs a
   // location list.
+  // FIXME: use DWARFAttribute::mayHaveLocationDescription().
   else if (AttrSpec.Attr == dwarf::DW_AT_location ||
-           AttrSpec.Attr == dwarf::DW_AT_frame_base)
+         AttrSpec.Attr == dwarf::DW_AT_frame_base)
     Unit.noteLocationAttribute(Patch, Info.PCOffset);
   else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
     Info.IsDeclaration = true;
@@ -1213,7 +1290,8 @@ unsigned DwarfLinker::DIECloner::cloneSc
 unsigned DwarfLinker::DIECloner::cloneAttribute(
     DIE &Die, const DWARFDie &InputDIE, const DebugMapObject &DMO,
     CompileUnit &Unit, OffsetsStringPool &StringPool, const DWARFFormValue &Val,
-    const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info) {
+    const AttributeSpec AttrSpec, unsigned AttrSize, AttributesInfo &Info,
+    bool IsLittleEndian) {
   const DWARFUnit &U = Unit.getOrigUnit();
 
   switch (AttrSpec.Form) {
@@ -1232,7 +1310,8 @@ unsigned DwarfLinker::DIECloner::cloneAt
   case dwarf::DW_FORM_block2:
   case dwarf::DW_FORM_block4:
   case dwarf::DW_FORM_exprloc:
-    return cloneBlockAttribute(Die, AttrSpec, Val, AttrSize);
+    return cloneBlockAttribute(Die, DMO, Unit, AttrSpec, Val, AttrSize,
+                               IsLittleEndian);
   case dwarf::DW_FORM_addr:
     return cloneAddressAttribute(Die, AttrSpec, Val, Unit, Info);
   case dwarf::DW_FORM_data1:
@@ -1264,7 +1343,7 @@ unsigned DwarfLinker::DIECloner::cloneAt
 ///
 /// \returns whether any reloc has been applied.
 bool DwarfLinker::RelocationManager::applyValidRelocs(
-    MutableArrayRef<char> Data, uint32_t BaseOffset, bool isLittleEndian) {
+    MutableArrayRef<char> Data, uint32_t BaseOffset, bool IsLittleEndian) {
   assert((NextValidReloc == 0 ||
           BaseOffset > ValidRelocs[NextValidReloc - 1].Offset) &&
          "BaseOffset should only be increasing.");
@@ -1288,7 +1367,7 @@ bool DwarfLinker::RelocationManager::app
     uint64_t Value = ValidReloc.Mapping->getValue().BinaryAddress;
     Value += ValidReloc.Addend;
     for (unsigned i = 0; i != ValidReloc.Size; ++i) {
-      unsigned Index = isLittleEndian ? i : (ValidReloc.Size - i - 1);
+      unsigned Index = IsLittleEndian ? i : (ValidReloc.Size - i - 1);
       Buf[i] = uint8_t(Value >> (Index * 8));
     }
     assert(ValidReloc.Size <= sizeof(Buf));
@@ -1370,12 +1449,10 @@ shouldSkipAttribute(DWARFAbbreviationDec
   }
 }
 
-DIE *DwarfLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
-                                      const DebugMapObject &DMO,
-                                      CompileUnit &Unit,
-                                      OffsetsStringPool &StringPool,
-                                      int64_t PCOffset, uint32_t OutOffset,
-                                      unsigned Flags, DIE *Die) {
+DIE *DwarfLinker::DIECloner::cloneDIE(
+    const DWARFDie &InputDIE, const DebugMapObject &DMO, CompileUnit &Unit,
+    OffsetsStringPool &StringPool, int64_t PCOffset, uint32_t OutOffset,
+    unsigned Flags, bool IsLittleEndian, DIE *Die) {
   DWARFUnit &U = Unit.getOrigUnit();
   unsigned Idx = U.getDIEIndex(InputDIE);
   CompileUnit::DIEInfo &Info = Unit.getInfo(Idx);
@@ -1481,7 +1558,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(co
     AttrSize = Offset - AttrSize;
 
     OutOffset += cloneAttribute(*Die, InputDIE, DMO, Unit, StringPool, Val,
-                                AttrSpec, AttrSize, AttrInfo);
+                                AttrSpec, AttrSize, AttrInfo, IsLittleEndian);
   }
 
   // Look for accelerator entries.
@@ -1556,7 +1633,7 @@ DIE *DwarfLinker::DIECloner::cloneDIE(co
   // Recursively clone children.
   for (auto Child : InputDIE.children()) {
     if (DIE *Clone = cloneDIE(Child, DMO, Unit, StringPool, PCOffset, OutOffset,
-                              Flags)) {
+                              Flags, IsLittleEndian)) {
       Die->addChild(Clone);
       OutOffset = Clone->getOffset() + Clone->getSize();
     }
@@ -2033,7 +2110,8 @@ bool DwarfLinker::registerModuleReferenc
     const DWARFDie &CUDie, const DWARFUnit &Unit, DebugMap &ModuleMap,
     const DebugMapObject &DMO, RangesTy &Ranges, OffsetsStringPool &StringPool,
     UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts,
-    uint64_t ModulesEndOffset, unsigned &UnitID, unsigned Indent, bool Quiet) {
+    uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian,
+    unsigned Indent, bool Quiet) {
   std::string PCMfile = dwarf::toString(
       CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
   if (PCMfile.empty())
@@ -2075,10 +2153,10 @@ bool DwarfLinker::registerModuleReferenc
   // Cyclic dependencies are disallowed by Clang, but we still
   // shouldn't run into an infinite loop, so mark it as processed now.
   ClangModules.insert({PCMfile, DwoId});
-  if (Error E =
-          loadClangModule(PCMfile, PCMpath, Name, DwoId, ModuleMap, DMO, Ranges,
-                          StringPool, UniquingStringPool, ODRContexts,
-                          ModulesEndOffset, UnitID, Indent + 2, Quiet)) {
+  if (Error E = loadClangModule(PCMfile, PCMpath, Name, DwoId, ModuleMap, DMO,
+                                Ranges, StringPool, UniquingStringPool,
+                                ODRContexts, ModulesEndOffset, UnitID,
+                                IsLittleEndian, Indent + 2, Quiet)) {
     consumeError(std::move(E));
     return false;
   }
@@ -2112,7 +2190,8 @@ Error DwarfLinker::loadClangModule(
     uint64_t DwoId, DebugMap &ModuleMap, const DebugMapObject &DMO,
     RangesTy &Ranges, OffsetsStringPool &StringPool,
     UniquingStringPool &UniquingStringPool, DeclContextTree &ODRContexts,
-    uint64_t ModulesEndOffset, unsigned &UnitID, unsigned Indent, bool Quiet) {
+    uint64_t ModulesEndOffset, unsigned &UnitID, bool IsLittleEndian,
+    unsigned Indent, bool Quiet) {
   SmallString<80> Path(Options.PrependPath);
   if (sys::path::is_relative(Filename))
     sys::path::append(Path, ModulePath, Filename);
@@ -2174,7 +2253,8 @@ Error DwarfLinker::loadClangModule(
       continue;
     if (!registerModuleReference(CUDie, *CU, ModuleMap, DMO, Ranges, StringPool,
                                  UniquingStringPool, ODRContexts,
-                                 ModulesEndOffset, UnitID, Indent, Quiet)) {
+                                 ModulesEndOffset, UnitID, IsLittleEndian,
+                                 Indent, Quiet)) {
       if (Unit) {
         std::string Err =
             (Filename +
@@ -2218,13 +2298,14 @@ Error DwarfLinker::loadClangModule(
   UnitListTy CompileUnits;
   CompileUnits.push_back(std::move(Unit));
   DIECloner(*this, RelocMgr, DIEAlloc, CompileUnits, Options)
-      .cloneAllCompileUnits(*DwarfContext, DMO, Ranges, StringPool);
+      .cloneAllCompileUnits(*DwarfContext, DMO, Ranges, StringPool,
+                            IsLittleEndian);
   return Error::success();
 }
 
 void DwarfLinker::DIECloner::cloneAllCompileUnits(
     DWARFContext &DwarfContext, const DebugMapObject &DMO, RangesTy &Ranges,
-    OffsetsStringPool &StringPool) {
+    OffsetsStringPool &StringPool, bool IsLittleEndian) {
   if (!Linker.Streamer)
     return;
 
@@ -2240,7 +2321,8 @@ void DwarfLinker::DIECloner::cloneAllCom
       // already has a DIE inside of it.
       CurrentUnit->createOutputDIE();
       cloneDIE(InputDIE, DMO, *CurrentUnit, StringPool, 0 /* PC offset */,
-               11 /* Unit Header size */, 0, CurrentUnit->getOutputUnitDIE());
+               11 /* Unit Header size */, 0, IsLittleEndian,
+               CurrentUnit->getOutputUnitDIE());
     }
 
     Linker.OutputDebugInfoSize = CurrentUnit->computeNextUnitOffset();
@@ -2260,7 +2342,16 @@ void DwarfLinker::DIECloner::cloneAllCom
       continue;
 
     Linker.patchRangesForUnit(*CurrentUnit, DwarfContext, DMO);
-    Linker.Streamer->emitLocationsForUnit(*CurrentUnit, DwarfContext);
+    auto ProcessExpr = [&](StringRef Bytes, SmallVectorImpl<uint8_t> &Buffer) {
+      DWARFUnit &OrigUnit = CurrentUnit->getOrigUnit();
+      DataExtractor Data(Bytes, IsLittleEndian, OrigUnit.getAddressByteSize());
+      cloneExpression(Data,
+                      DWARFExpression(Data, OrigUnit.getVersion(),
+                                      OrigUnit.getAddressByteSize()),
+                      DMO, *CurrentUnit, Buffer);
+    };
+    Linker.Streamer->emitLocationsForUnit(*CurrentUnit, DwarfContext,
+                                          ProcessExpr);
   }
 
   if (Linker.Options.NoOutput)
@@ -2490,7 +2581,8 @@ bool DwarfLinker::link(const DebugMap &M
       if (CUDie && !LLVM_UNLIKELY(Options.Update))
         registerModuleReference(CUDie, *CU, ModuleMap, LinkContext.DMO,
                                 LinkContext.Ranges, OffsetsStringPool,
-                                UniquingStringPool, ODRContexts, 0, UnitID);
+                                UniquingStringPool, ODRContexts, 0, UnitID,
+                                LinkContext.DwarfContext->isLittleEndian());
     }
   }
 
@@ -2583,7 +2675,8 @@ bool DwarfLinker::link(const DebugMap &M
       DIECloner(*this, LinkContext.RelocMgr, DIEAlloc, LinkContext.CompileUnits,
                 Options)
           .cloneAllCompileUnits(*LinkContext.DwarfContext, LinkContext.DMO,
-                                LinkContext.Ranges, OffsetsStringPool);
+                                LinkContext.Ranges, OffsetsStringPool,
+                                LinkContext.DwarfContext->isLittleEndian());
     if (!Options.NoOutput && !LinkContext.CompileUnits.empty() &&
         LLVM_LIKELY(!Options.Update))
       patchFrameInfoForObject(

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.h?rev=355148&r1=355147&r2=355148&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.h (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.h Thu Feb 28 14:12:32 2019
@@ -136,7 +136,7 @@ private:
                             CompileUnit::DIEInfo &Info);
 
     bool applyValidRelocs(MutableArrayRef<char> Data, uint32_t BaseOffset,
-                          bool isLittleEndian);
+                          bool IsLittleEndian);
   };
 
   /// Keeps track of data associated with one object during linking.
@@ -200,7 +200,8 @@ private:
                                UniquingStringPool &UniquingStringPoolStringPool,
                                DeclContextTree &ODRContexts,
                                uint64_t ModulesEndOffset, unsigned &UnitID,
-                               unsigned Indent = 0, bool Quiet = false);
+                               bool IsLittleEndian, unsigned Indent = 0,
+                               bool Quiet = false);
 
   /// Recursively add the debug info in this clang module .pcm
   /// file (and all the modules imported by it in a bottom-up fashion)
@@ -211,8 +212,8 @@ private:
                         RangesTy &Ranges, OffsetsStringPool &OffsetsStringPool,
                         UniquingStringPool &UniquingStringPool,
                         DeclContextTree &ODRContexts, uint64_t ModulesEndOffset,
-                        unsigned &UnitID, unsigned Indent = 0,
-                        bool Quiet = false);
+                        unsigned &UnitID, bool IsLittleEndian,
+                        unsigned Indent = 0, bool Quiet = false);
 
   /// Flags passed to DwarfLinker::lookForDIEsToKeep
   enum TraversalFlags {
@@ -236,6 +237,8 @@ private:
                          CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
                          unsigned Flags);
 
+  /// Check if a variable describing DIE should be kept.
+  /// \returns updated TraversalFlags.
   unsigned shouldKeepVariableDIE(RelocationManager &RelocMgr,
                                  const DWARFDie &DIE, CompileUnit &Unit,
                                  CompileUnit::DIEInfo &MyInfo, unsigned Flags);
@@ -286,14 +289,15 @@ private:
     DIE *cloneDIE(const DWARFDie &InputDIE, const DebugMapObject &DMO,
                   CompileUnit &U, OffsetsStringPool &StringPool,
                   int64_t PCOffset, uint32_t OutOffset, unsigned Flags,
-                  DIE *Die = nullptr);
+                  bool IsLittleEndian, DIE *Die = nullptr);
 
     /// Construct the output DIE tree by cloning the DIEs we
     /// chose to keep above. If there are no valid relocs, then there's
     /// nothing to clone/emit.
     void cloneAllCompileUnits(DWARFContext &DwarfContext,
                               const DebugMapObject &DMO, RangesTy &Ranges,
-                              OffsetsStringPool &StringPool);
+                              OffsetsStringPool &StringPool,
+                              bool IsLittleEndian);
 
   private:
     using AttributeSpec = DWARFAbbreviationDeclaration::AttributeSpec;
@@ -335,7 +339,7 @@ private:
                             OffsetsStringPool &StringPool,
                             const DWARFFormValue &Val,
                             const AttributeSpec AttrSpec, unsigned AttrSize,
-                            AttributesInfo &AttrInfo);
+                            AttributesInfo &AttrInfo, bool IsLittleEndian);
 
     /// Clone a string attribute described by \p AttrSpec and add
     /// it to \p Die.
@@ -355,11 +359,18 @@ private:
                                         const DebugMapObject &DMO,
                                         CompileUnit &Unit);
 
+    /// Clone a DWARF expression that may be referencing another DIE.
+    void cloneExpression(DataExtractor &Data, DWARFExpression Expression,
+                         const DebugMapObject &DMO, CompileUnit &Unit,
+                         SmallVectorImpl<uint8_t> &OutputBuffer);
+
     /// Clone an attribute referencing another DIE and add
     /// it to \p Die.
     /// \returns the size of the new attribute.
-    unsigned cloneBlockAttribute(DIE &Die, AttributeSpec AttrSpec,
-                                 const DWARFFormValue &Val, unsigned AttrSize);
+    unsigned cloneBlockAttribute(DIE &Die, const DebugMapObject &DMO,
+                                 CompileUnit &Unit, AttributeSpec AttrSpec,
+                                 const DWARFFormValue &Val, unsigned AttrSize,
+                                 bool IsLittleEndian);
 
     /// Clone an attribute referencing another DIE and add
     /// it to \p Die.

Modified: llvm/trunk/tools/dsymutil/DwarfStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.cpp?rev=355148&r1=355147&r2=355148&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfStreamer.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfStreamer.cpp Thu Feb 28 14:12:32 2019
@@ -384,8 +384,9 @@ void DwarfStreamer::emitUnitRangesEntrie
 
 /// Emit location lists for \p Unit and update attributes to point to the new
 /// entries.
-void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
-                                         DWARFContext &Dwarf) {
+void DwarfStreamer::emitLocationsForUnit(
+    const CompileUnit &Unit, DWARFContext &Dwarf,
+    std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr) {
   const auto &Attributes = Unit.getLocationAttributes();
 
   if (Attributes.empty())
@@ -402,6 +403,7 @@ void DwarfStreamer::emitLocationsForUnit
   if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc)))
     UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc();
 
+  SmallVector<uint8_t, 32> Buffer;
   for (const auto &Attr : Attributes) {
     uint32_t Offset = Attr.first.get();
     Attr.first.set(LocSectionSize);
@@ -421,9 +423,13 @@ void DwarfStreamer::emitLocationsForUnit
       Asm->OutStreamer->EmitIntValue(High + LocPcOffset, AddressSize);
       uint64_t Length = Data.getU16(&Offset);
       Asm->OutStreamer->EmitIntValue(Length, 2);
-      // Just copy the bytes over.
+      // Copy the bytes into to the buffer, process them, emit them.
+      Buffer.reserve(Length);
+      Buffer.resize(0);
+      StringRef Input = InputSec.Data.substr(Offset, Length);
+      ProcessExpr(Input, Buffer);
       Asm->OutStreamer->EmitBytes(
-          StringRef(InputSec.Data.substr(Offset, Length)));
+          StringRef((const char *)Buffer.data(), Length));
       Offset += Length;
       LocSectionSize += Length + 2;
     }

Modified: llvm/trunk/tools/dsymutil/DwarfStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfStreamer.h?rev=355148&r1=355147&r2=355148&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfStreamer.h (original)
+++ llvm/trunk/tools/dsymutil/DwarfStreamer.h Thu Feb 28 14:12:32 2019
@@ -95,7 +95,9 @@ public:
   /// Emit the debug_loc contribution for \p Unit by copying the entries from
   /// \p Dwarf and offsetting them. Update the location attributes to point to
   /// the new entries.
-  void emitLocationsForUnit(const CompileUnit &Unit, DWARFContext &Dwarf);
+  void emitLocationsForUnit(
+      const CompileUnit &Unit, DWARFContext &Dwarf,
+      std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr);
 
   /// Emit the line table described in \p Rows into the debug_line section.
   void emitLineTableForUnit(MCDwarfLineTableParams Params,




More information about the llvm-commits mailing list