blob: 1503015f015575b21d3368e5d5bfc6768fc9187f [file] [log] [blame]
//===- DWARFLinkerUnit.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DWARFLinkerUnit.h"
#include "DWARFEmitterImpl.h"
#include "DebugLineSectionEmitter.h"
namespace llvm {
namespace dwarflinker_parallel {
void DwarfUnit::assignAbbrev(DIEAbbrev &Abbrev) {
// Check the set for priors.
FoldingSetNodeID ID;
Abbrev.Profile(ID);
void *InsertToken;
DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
// If it's newly added.
if (InSet) {
// Assign existing abbreviation number.
Abbrev.setNumber(InSet->getNumber());
} else {
// Add to abbreviation list.
Abbreviations.push_back(
std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
for (const auto &Attr : Abbrev.getData())
Abbreviations.back()->AddAttribute(Attr);
AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
// Assign the unique abbreviation number.
Abbrev.setNumber(Abbreviations.size());
Abbreviations.back()->setNumber(Abbreviations.size());
}
}
Error DwarfUnit::emitAbbreviations() {
const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs = getAbbreviations();
if (Abbrevs.empty())
return Error::success();
SectionDescriptor &AbbrevSection =
getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev);
// For each abbreviation.
for (const auto &Abbrev : Abbrevs)
emitDwarfAbbrevEntry(*Abbrev, AbbrevSection);
// Mark end of abbreviations.
encodeULEB128(0, AbbrevSection.OS);
return Error::success();
}
void DwarfUnit::emitDwarfAbbrevEntry(const DIEAbbrev &Abbrev,
SectionDescriptor &AbbrevSection) {
// Emit the abbreviations code (base 1 index.)
encodeULEB128(Abbrev.getNumber(), AbbrevSection.OS);
// Emit the abbreviations data.
// Emit its Dwarf tag type.
encodeULEB128(Abbrev.getTag(), AbbrevSection.OS);
// Emit whether it has children DIEs.
encodeULEB128((unsigned)Abbrev.hasChildren(), AbbrevSection.OS);
// For each attribute description.
const SmallVectorImpl<DIEAbbrevData> &Data = Abbrev.getData();
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
const DIEAbbrevData &AttrData = Data[i];
// Emit attribute type.
encodeULEB128(AttrData.getAttribute(), AbbrevSection.OS);
// Emit form type.
encodeULEB128(AttrData.getForm(), AbbrevSection.OS);
// Emit value for DW_FORM_implicit_const.
if (AttrData.getForm() == dwarf::DW_FORM_implicit_const)
encodeSLEB128(AttrData.getValue(), AbbrevSection.OS);
}
// Mark end of abbreviation.
encodeULEB128(0, AbbrevSection.OS);
encodeULEB128(0, AbbrevSection.OS);
}
Error DwarfUnit::emitDebugInfo(Triple &TargetTriple) {
DIE *OutUnitDIE = getOutUnitDIE();
if (OutUnitDIE == nullptr)
return Error::success();
// FIXME: Remove dependence on DwarfEmitterImpl/AsmPrinter and emit DIEs
// directly.
SectionDescriptor &OutSection =
getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object, OutSection.OS);
if (Error Err = Emitter.init(TargetTriple, "__DWARF"))
return Err;
// Emit compile unit header.
Emitter.emitCompileUnitHeader(*this);
size_t OffsetToAbbreviationTableOffset =
(getFormParams().Version >= 5) ? 8 : 6;
OutSection.notePatch(DebugOffsetPatch{
OffsetToAbbreviationTableOffset,
&getOrCreateSectionDescriptor(DebugSectionKind::DebugAbbrev)});
// Emit DIEs.
Emitter.emitDIE(*OutUnitDIE);
Emitter.finish();
// Set start offset ans size for .debug_info section.
OutSection.setSizesForSectionCreatedByAsmPrinter();
return Error::success();
}
Error DwarfUnit::emitDebugLine(Triple &TargetTriple,
const DWARFDebugLine::LineTable &OutLineTable) {
DebugLineSectionEmitter DebugLineEmitter(TargetTriple, *this);
return DebugLineEmitter.emit(OutLineTable);
}
/// Emit the pubnames or pubtypes section contribution for \p
/// Unit into \p Sec. The data is provided in \p Info.
std::optional<uint64_t>
DwarfUnit::emitPubAcceleratorEntry(SectionDescriptor &OutSection,
DwarfUnit::AccelInfo &Info,
std::optional<uint64_t> LengthOffset) {
if (!LengthOffset) {
// Emit the header.
OutSection.emitIntVal(0xBADDEF,
getFormParams().getDwarfOffsetByteSize()); // Length
LengthOffset = OutSection.OS.tell();
OutSection.emitIntVal(dwarf::DW_PUBNAMES_VERSION, 2); // Version
OutSection.notePatch(DebugOffsetPatch{
OutSection.OS.tell(),
&getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)});
OutSection.emitOffset(0xBADDEF); // Unit offset
OutSection.emitIntVal(getUnitSize(), 4); // Size
}
OutSection.emitOffset(Info.OutOffset);
// Emit the string itself.
OutSection.emitInplaceString(Info.String->first());
return LengthOffset;
}
/// Emit .debug_pubnames and .debug_pubtypes for \p Unit.
void DwarfUnit::emitPubAccelerators() {
std::optional<uint64_t> NamesLengthOffset;
std::optional<uint64_t> TypesLengthOffset;
AcceleratorRecords.forEach([&](DwarfUnit::AccelInfo &Info) {
if (Info.AvoidForPubSections)
return;
switch (Info.Type) {
case DwarfUnit::AccelType::Name: {
NamesLengthOffset = emitPubAcceleratorEntry(
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames), Info,
NamesLengthOffset);
} break;
case DwarfUnit::AccelType::Type: {
TypesLengthOffset = emitPubAcceleratorEntry(
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes), Info,
TypesLengthOffset);
} break;
default: {
// Nothing to do.
} break;
}
});
if (NamesLengthOffset) {
SectionDescriptor &OutSection =
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubNames);
OutSection.emitIntVal(0, 4); // End marker.
OutSection.apply(*NamesLengthOffset -
OutSection.getFormParams().getDwarfOffsetByteSize(),
dwarf::DW_FORM_sec_offset,
OutSection.OS.tell() - *NamesLengthOffset);
}
if (TypesLengthOffset) {
SectionDescriptor &OutSection =
getOrCreateSectionDescriptor(DebugSectionKind::DebugPubTypes);
OutSection.emitIntVal(0, 4); // End marker.
OutSection.apply(*TypesLengthOffset -
OutSection.getFormParams().getDwarfOffsetByteSize(),
dwarf::DW_FORM_sec_offset,
OutSection.OS.tell() - *TypesLengthOffset);
}
}
} // end of namespace dwarflinker_parallel
} // end of namespace llvm