1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

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
This commit is contained in:
Adrian Prantl 2019-02-28 22:12:32 +00:00
parent 21b919ec87
commit 64b92e8c26
9 changed files with 279 additions and 51 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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)

Binary file not shown.

View File

@ -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")

View File

@ -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(

View File

@ -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.

View File

@ -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;
}

View File

@ -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,