summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2019-02-28 22:12:32 +0000
committerAdrian Prantl <aprantl@apple.com>2019-02-28 22:12:32 +0000
commitfa37a00044c93d9fa7cf7b2ac6d3c20c71348f10 (patch)
tree16b31ef48f60ea3d2daf8f5436ea85bd9dba635f
parent844b5d6985098ec344062351ff3628fa5814736c (diff)
downloadbcm5719-llvm-fa37a00044c93d9fa7cf7b2ac6d3c20c71348f10.tar.gz
bcm5719-llvm-fa37a00044c93d9fa7cf7b2ac6d3c20c71348f10.zip
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 llvm-svn: 355148
-rw-r--r--llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h4
-rw-r--r--llvm/lib/DebugInfo/DWARF/DWARFDie.cpp40
-rw-r--r--llvm/test/tools/dsymutil/Inputs/op-convert.ll45
-rw-r--r--llvm/test/tools/dsymutil/Inputs/op-convert.macho.x86_64bin0 -> 2092 bytes
-rw-r--r--llvm/test/tools/dsymutil/X86/op-convert.test33
-rw-r--r--llvm/tools/dsymutil/DwarfLinker.cpp161
-rw-r--r--llvm/tools/dsymutil/DwarfLinker.h29
-rw-r--r--llvm/tools/dsymutil/DwarfStreamer.cpp14
-rw-r--r--llvm/tools/dsymutil/DwarfStreamer.h4
9 files changed, 279 insertions, 51 deletions
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
index fc6f0a44360..96e622ccc03 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
@@ -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;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index d1396887645..4cd69bc8017 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -312,9 +312,7 @@ static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
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::attribute_iterator::operator++() {
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;
+ }
+}
diff --git a/llvm/test/tools/dsymutil/Inputs/op-convert.ll b/llvm/test/tools/dsymutil/Inputs/op-convert.ll
new file mode 100644
index 00000000000..10dd3febfeb
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/op-convert.ll
@@ -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)
diff --git a/llvm/test/tools/dsymutil/Inputs/op-convert.macho.x86_64 b/llvm/test/tools/dsymutil/Inputs/op-convert.macho.x86_64
new file mode 100644
index 00000000000..c4d85a31235
--- /dev/null
+++ b/llvm/test/tools/dsymutil/Inputs/op-convert.macho.x86_64
Binary files differ
diff --git a/llvm/test/tools/dsymutil/X86/op-convert.test b/llvm/test/tools/dsymutil/X86/op-convert.test
new file mode 100644
index 00000000000..9cdc1af3e06
--- /dev/null
+++ b/llvm/test/tools/dsymutil/X86/op-convert.test
@@ -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")
+
diff --git a/llvm/tools/dsymutil/DwarfLinker.cpp b/llvm/tools/dsymutil/DwarfLinker.cpp
index f3ffff93046..e3749a32a16 100644
--- a/llvm/tools/dsymutil/DwarfLinker.cpp
+++ b/llvm/tools/dsymutil/DwarfLinker.cpp
@@ -125,7 +125,6 @@ static DWARFDie resolveDIEReference(const DwarfLinker &Linker,
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::shouldKeepVariableDIE(RelocationManager &RelocMgr,
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(RelocationManager &RelocMgr,
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::cloneDieReferenceAttribute(
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::cloneBlockAttribute(DIE &Die,
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::cloneScalarAttribute(
// 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::cloneScalarAttribute(
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::cloneAttribute(
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::cloneAttribute(
///
/// \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::applyValidRelocs(
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(DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
}
}
-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(const DWARFDie &InputDIE,
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(const DWARFDie &InputDIE,
// 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::registerModuleReference(
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::registerModuleReference(
// 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::cloneAllCompileUnits(
// 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::cloneAllCompileUnits(
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 &Map) {
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 &Map) {
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(
diff --git a/llvm/tools/dsymutil/DwarfLinker.h b/llvm/tools/dsymutil/DwarfLinker.h
index 159572743b9..fdc86cf442a 100644
--- a/llvm/tools/dsymutil/DwarfLinker.h
+++ b/llvm/tools/dsymutil/DwarfLinker.h
@@ -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.
diff --git a/llvm/tools/dsymutil/DwarfStreamer.cpp b/llvm/tools/dsymutil/DwarfStreamer.cpp
index 2b2c94a3899..fbea7426a52 100644
--- a/llvm/tools/dsymutil/DwarfStreamer.cpp
+++ b/llvm/tools/dsymutil/DwarfStreamer.cpp
@@ -384,8 +384,9 @@ void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
/// 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(const CompileUnit &Unit,
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(const CompileUnit &Unit,
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;
}
diff --git a/llvm/tools/dsymutil/DwarfStreamer.h b/llvm/tools/dsymutil/DwarfStreamer.h
index 7477004eecf..0b71d9f49bf 100644
--- a/llvm/tools/dsymutil/DwarfStreamer.h
+++ b/llvm/tools/dsymutil/DwarfStreamer.h
@@ -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,
OpenPOWER on IntegriCloud