typedef HalfOpenIntervalMap<uint64_t, int64_t> FunctionIntervals;
+// FIXME: Delete this structure once DIE::Values has a stable iterator we can
+// use instead.
+struct PatchLocation {
+ DIE *Die;
+ unsigned Index;
+
+ PatchLocation() : Die(nullptr), Index(0) {}
+ PatchLocation(DIE &Die, unsigned Index) : Die(&Die), Index(Index) {}
+ PatchLocation(DIE &Die)
+ : Die(&Die), Index(std::distance(Die.values_begin(), Die.values_end())) {}
+
+ void set(uint64_t New) const {
+ assert(Die);
+ assert((signed)Index <
+ std::distance(Die->values_begin(), Die->values_end()));
+ const auto &Old = Die->values_begin()[Index];
+ assert(Old.getType() == DIEValue::isInteger);
+ Die->setValue(Index,
+ DIEValue(Old.getAttribute(), Old.getForm(), DIEInteger(New)));
+ }
+
+ uint64_t get() const {
+ assert(Die);
+ assert((signed)Index <
+ std::distance(Die->values_begin(), Die->values_end()));
+ assert(Die->values_begin()[Index].getType() == DIEValue::isInteger);
+ return Die->values_begin()[Index].getDIEInteger().getValue();
+ }
+};
+
/// \brief Stores all information relating to a compile unit, be it in
/// its original instance in the object file to its brand new cloned
/// and linked DIE tree.
CompileUnit(DWARFUnit &OrigUnit, unsigned ID)
: OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0), RangeAlloc(),
- Ranges(RangeAlloc), UnitRangeAttribute(nullptr) {
+ Ranges(RangeAlloc) {
Info.resize(OrigUnit.getNumDIEs());
}
uint64_t getLowPc() const { return LowPc; }
uint64_t getHighPc() const { return HighPc; }
- DIEInteger *getUnitRangesAttribute() const { return UnitRangeAttribute; }
+ Optional<PatchLocation> getUnitRangesAttribute() const {
+ return UnitRangeAttribute;
+ }
const FunctionIntervals &getFunctionRanges() const { return Ranges; }
- const std::vector<DIEInteger *> &getRangesAttributes() const {
+ const std::vector<PatchLocation> &getRangesAttributes() const {
return RangeAttributes;
}
- const std::vector<std::pair<DIEInteger *, int64_t>> &
+ const std::vector<std::pair<PatchLocation, int64_t>> &
getLocationAttributes() const {
return LocationAttributes;
}
/// RefUnit by \p Attr. The attribute should be fixed up later to
/// point to the absolute offset of \p Die in the debug_info section.
void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
- DIEInteger *Attr);
+ PatchLocation Attr);
/// \brief Apply all fixups recored by noteForwardReference().
void fixupForwardReferences();
/// \brief Keep track of a DW_AT_range attribute that we will need to
/// patch up later.
- void noteRangeAttribute(const DIE &Die, DIEInteger *Attr);
+ void noteRangeAttribute(const DIE &Die, PatchLocation Attr);
/// \brief Keep track of a location attribute pointing to a location
/// list in the debug_loc section.
- void noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset);
+ void noteLocationAttribute(PatchLocation Attr, int64_t PcOffset);
/// \brief Add a name accelerator entry for \p Die with \p Name
/// which is stored in the string table at \p Offset.
/// The offsets for the attributes in this array couldn't be set while
/// cloning because for cross-cu forward refences the target DIE's
/// offset isn't known you emit the reference attribute.
- std::vector<std::tuple<DIE *, const CompileUnit *, DIEInteger *>>
+ std::vector<std::tuple<DIE *, const CompileUnit *, PatchLocation>>
ForwardDIEReferences;
FunctionIntervals::Allocator RangeAlloc;
/// \brief DW_AT_ranges attributes to patch after we have gathered
/// all the unit's function addresses.
/// @{
- std::vector<DIEInteger *> RangeAttributes;
- DIEInteger *UnitRangeAttribute;
+ std::vector<PatchLocation> RangeAttributes;
+ Optional<PatchLocation> UnitRangeAttribute;
/// @}
/// \brief Location attributes that need to be transfered from th
/// original debug_loc section to the liked one. They are stored
/// along with the PC offset that is to be applied to their
/// function's address.
- std::vector<std::pair<DIEInteger *, int64_t>> LocationAttributes;
+ std::vector<std::pair<PatchLocation, int64_t>> LocationAttributes;
/// \brief Accelerator entries for the unit, both for the pub*
/// sections and the apple* ones.
/// \brief Keep track of a forward cross-cu reference from this unit
/// to \p Die that lives in \p RefUnit.
void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
- DIEInteger *Attr) {
+ PatchLocation Attr) {
ForwardDIEReferences.emplace_back(Die, RefUnit, Attr);
}
for (const auto &Ref : ForwardDIEReferences) {
DIE *RefDie;
const CompileUnit *RefUnit;
- DIEInteger *Attr;
+ PatchLocation Attr;
std::tie(RefDie, RefUnit, Attr) = Ref;
- Attr->setValue(RefDie->getOffset() + RefUnit->getStartOffset());
+ Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
}
}
this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
}
-void CompileUnit::noteRangeAttribute(const DIE &Die, DIEInteger *Attr) {
+void CompileUnit::noteRangeAttribute(const DIE &Die, PatchLocation Attr) {
if (Die.getTag() != dwarf::DW_TAG_compile_unit)
RangeAttributes.push_back(Attr);
else
UnitRangeAttribute = Attr;
}
-void CompileUnit::noteLocationAttribute(DIEInteger *Attr, int64_t PcOffset) {
+void CompileUnit::noteLocationAttribute(PatchLocation Attr, int64_t PcOffset) {
LocationAttributes.emplace_back(Attr, PcOffset);
}
/// point to the new entries.
void DwarfStreamer::emitLocationsForUnit(const CompileUnit &Unit,
DWARFContext &Dwarf) {
- const std::vector<std::pair<DIEInteger *, int64_t>> &Attributes =
- Unit.getLocationAttributes();
+ const auto &Attributes = Unit.getLocationAttributes();
if (Attributes.empty())
return;
UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
for (const auto &Attr : Attributes) {
- uint32_t Offset = Attr.first->getValue();
- Attr.first->setValue(LocSectionSize);
+ uint32_t Offset = Attr.first.get();
+ Attr.first.set(LocSectionSize);
// This is the quantity to add to the old location address to get
// the correct address for the new one.
int64_t LocPcOffset = Attr.second + UnitPcOffset;
return false;
const auto &ValidReloc = ValidRelocs[NextValidReloc++];
+ const auto &Mapping = ValidReloc.Mapping->getValue();
if (Options.Verbose)
outs() << "Found valid debug map entry: " << ValidReloc.Mapping->getKey()
<< " " << format("\t%016" PRIx64 " => %016" PRIx64,
- ValidReloc.Mapping->getValue().ObjectAddress,
- ValidReloc.Mapping->getValue().BinaryAddress);
+ uint64_t(Mapping.ObjectAddress),
+ uint64_t(Mapping.BinaryAddress));
- Info.AddrAdjust = int64_t(ValidReloc.Mapping->getValue().BinaryAddress) +
- ValidReloc.Addend -
- ValidReloc.Mapping->getValue().ObjectAddress;
+ Info.AddrAdjust = int64_t(Mapping.BinaryAddress) +
+ ValidReloc.Addend - Mapping.ObjectAddress;
Info.InDebugMap = true;
return true;
}
const char *String = *Val.getAsCString(&U);
unsigned Offset = StringPool.getStringOffset(String);
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_strp,
- new (DIEAlloc) DIEInteger(Offset));
+ DIEInteger(Offset));
return 4;
}
// to find the unit offset. (We don't have a DwarfDebug)
// FIXME: we should be able to design DIEEntry reliance on
// DwarfDebug away.
- DIEInteger *Attr;
+ uint64_t Attr;
if (Ref < InputDIE.getOffset()) {
// We must have already cloned that DIE.
uint32_t NewRefOffset =
RefUnit->getStartOffset() + NewRefDie->getOffset();
- Attr = new (DIEAlloc) DIEInteger(NewRefOffset);
+ Attr = NewRefOffset;
} else {
// A forward reference. Note and fixup later.
- Attr = new (DIEAlloc) DIEInteger(0xBADDEF);
- Unit.noteForwardReference(NewRefDie, RefUnit, Attr);
+ Attr = 0xBADDEF;
+ Unit.noteForwardReference(NewRefDie, RefUnit, PatchLocation(Die));
}
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::DW_FORM_ref_addr,
- Attr);
+ DIEInteger(Attr));
return AttrSize;
}
Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form),
- new (DIEAlloc) DIEEntry(*NewRefDie));
+ DIEEntry(*NewRefDie));
return AttrSize;
}
const DWARFFormValue &Val,
unsigned AttrSize) {
DIE *Attr;
- DIEValue *Value;
+ 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();
+ Loc = new (DIEAlloc) DIELoc;
DIELocs.push_back(Loc);
} else {
- Block = new (DIEAlloc) DIEBlock();
+ Block = new (DIEAlloc) DIEBlock;
DIEBlocks.push_back(Block);
}
Attr = Loc ? static_cast<DIE *>(Loc) : static_cast<DIE *>(Block);
- Value = Loc ? static_cast<DIEValue *>(Loc) : static_cast<DIEValue *>(Block);
+
+ if (Loc)
+ Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
+ dwarf::Form(AttrSpec.Form), Loc);
+ else
+ Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
+ dwarf::Form(AttrSpec.Form), Block);
ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
for (auto Byte : Bytes)
Attr->addValue(static_cast<dwarf::Attribute>(0), dwarf::DW_FORM_data1,
- new (DIEAlloc) DIEInteger(Byte));
+ 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()).
else
Block->ComputeSize(&Streamer->getAsmPrinter());
}
- Die.addValue(dwarf::Attribute(AttrSpec.Attr), dwarf::Form(AttrSpec.Form),
- Value);
+ Die.addValue(Value);
return AttrSize;
}
}
Die.addValue(static_cast<dwarf::Attribute>(AttrSpec.Attr),
- static_cast<dwarf::Form>(AttrSpec.Form),
- new (DIEAlloc) DIEInteger(Addr));
+ static_cast<dwarf::Form>(AttrSpec.Form), DIEInteger(Addr));
return Unit.getOrigUnit().getAddressByteSize();
}
&Unit.getOrigUnit(), &InputDIE);
return 0;
}
- DIEInteger *Attr = new (DIEAlloc) DIEInteger(Value);
+ DIEInteger Attr(Value);
if (AttrSpec.Attr == dwarf::DW_AT_ranges)
- Unit.noteRangeAttribute(Die, Attr);
+ Unit.noteRangeAttribute(Die, PatchLocation(Die));
// 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.
else if (AttrSpec.Attr == dwarf::DW_AT_location ||
AttrSpec.Attr == dwarf::DW_AT_frame_base)
- Unit.noteLocationAttribute(Attr, Info.PCOffset);
+ Unit.noteLocationAttribute(PatchLocation(Die), Info.PCOffset);
else if (AttrSpec.Attr == dwarf::DW_AT_declaration && Value)
Info.IsDeclaration = true;
Unit.addTypeAccelerator(Die, AttrInfo.Name, AttrInfo.NameOffset);
}
- DIEAbbrev &NewAbbrev = Die->getAbbrev();
+ DIEAbbrev NewAbbrev = Die->generateAbbrev();
// If a scope DIE is kept, we must have kept at least one child. If
// it's not the case, we'll just be emitting one wasteful end of
// children marker, but things won't break.
if (InputDIE.hasChildren())
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
// Assign a permanent abbrev number
- AssignAbbrev(Die->getAbbrev());
+ AssignAbbrev(NewAbbrev);
+ Die->setAbbrevNumber(NewAbbrev.getNumber());
// Add the size of the abbreviation number to the output offset.
OutOffset += getULEB128Size(Die->getAbbrevNumber());
UnitPcOffset = int64_t(OrigLowPc) - Unit.getLowPc();
for (const auto &RangeAttribute : Unit.getRangesAttributes()) {
- uint32_t Offset = RangeAttribute->getValue();
- RangeAttribute->setValue(Streamer->getRangesSectionSize());
+ uint32_t Offset = RangeAttribute.get();
+ RangeAttribute.set(Streamer->getRangesSectionSize());
RangeList.extract(RangeExtractor, &Offset);
const auto &Entries = RangeList.getEntries();
const DWARFDebugRangeList::RangeListEntry &First = Entries.front();
/// but for the sake of initial bit-for-bit compatibility with legacy
/// dsymutil, we have to do it in a delayed pass.
void DwarfLinker::generateUnitRanges(CompileUnit &Unit) const {
- DIEInteger *Attr = Unit.getUnitRangesAttribute();
+ auto Attr = Unit.getUnitRangesAttribute();
if (Attr)
- Attr->setValue(Streamer->getRangesSectionSize());
- Streamer->emitUnitRangesEntries(Unit, Attr != nullptr);
+ Attr->set(Streamer->getRangesSectionSize());
+ Streamer->emitUnitRangesEntries(Unit, static_cast<bool>(Attr));
}
/// \brief Insert the new line info sequence \p Seq into the current
// Update the cloned DW_AT_stmt_list with the correct debug_line offset.
if (auto *OutputDIE = Unit.getOutputUnitDIE()) {
- const auto &Abbrev = OutputDIE->getAbbrev().getData();
- auto Stmt = std::find_if(
- Abbrev.begin(), Abbrev.end(), [](const DIEAbbrevData &AbbrevData) {
- return AbbrevData.getAttribute() == dwarf::DW_AT_stmt_list;
- });
- assert(Stmt < Abbrev.end() && "Didn't find DW_AT_stmt_list in cloned DIE!");
- DIEInteger *StmtAttr =
- cast<DIEInteger>(OutputDIE->getValues()[Stmt - Abbrev.begin()]);
- StmtAttr->setValue(Streamer->getLineSectionSize());
+ auto Stmt = std::find_if(OutputDIE->values_begin(), OutputDIE->values_end(),
+ [](const DIEValue &Value) {
+ return Value.getAttribute() == dwarf::DW_AT_stmt_list;
+ });
+ assert(Stmt != OutputDIE->values_end() &&
+ "Didn't find DW_AT_stmt_list in cloned DIE!");
+ OutputDIE->setValue(Stmt - OutputDIE->values_begin(),
+ DIEValue(Stmt->getAttribute(), Stmt->getForm(),
+ DIEInteger(Streamer->getLineSectionSize())));
}
// Parse the original line info for the unit.