#include "llvm/DWARFLinker/Classic/DWARFLinker.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/NonRelocatableStringpool.h"
#include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h"
#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
#include "llvm/DWARFLinker/Utils.h"
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/ThreadPool.h"
#include <vector>
namespace llvm {
usingnamespacedwarf_linker;
usingnamespacedwarf_linker::classic;
struct DebugInfoSize { … };
static uint64_t getDebugInfoSize(DWARFContext &Dwarf) { … }
static CompileUnit *getUnitForOffset(const UnitListTy &Units, uint64_t Offset) { … }
DWARFDie DWARFLinker::resolveDIEReference(const DWARFFile &File,
const UnitListTy &Units,
const DWARFFormValue &RefValue,
const DWARFDie &DIE,
CompileUnit *&RefCU) { … }
static bool isODRAttribute(uint16_t Attr) { … }
static bool isTypeTag(uint16_t Tag) { … }
bool DWARFLinker::DIECloner::getDIENames(const DWARFDie &Die,
AttributesInfo &Info,
OffsetsStringPool &StringPool,
bool StripTemplate) { … }
static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) { … }
static void analyzeImportedModule(
const DWARFDie &DIE, CompileUnit &CU,
DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces,
std::function<void(const Twine &, const DWARFDie &)> ReportWarning) { … }
enum class ContextWorklistItemType : uint8_t { … };
struct ContextWorklistItem { … };
static bool updatePruning(const DWARFDie &Die, CompileUnit &CU,
uint64_t ModulesEndOffset) { … }
static void updateChildPruning(const DWARFDie &Die, CompileUnit &CU,
CompileUnit::DIEInfo &ChildInfo) { … }
static void analyzeContextInfo(
const DWARFDie &DIE, unsigned ParentIdx, CompileUnit &CU,
DeclContext *CurrentDeclContext, DeclContextTree &Contexts,
uint64_t ModulesEndOffset,
DWARFLinkerBase::SwiftInterfacesMapTy *ParseableSwiftInterfaces,
std::function<void(const Twine &, const DWARFDie &)> ReportWarning) { … }
static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) { … }
void DWARFLinker::cleanupAuxiliarryData(LinkContext &Context) { … }
static bool isTlsAddressCode(uint8_t DW_OP_Code) { … }
std::pair<bool, std::optional<int64_t>>
DWARFLinker::getVariableRelocAdjustment(AddressesMap &RelocMgr,
const DWARFDie &DIE) { … }
unsigned DWARFLinker::shouldKeepVariableDIE(AddressesMap &RelocMgr,
const DWARFDie &DIE,
CompileUnit::DIEInfo &MyInfo,
unsigned Flags) { … }
unsigned DWARFLinker::shouldKeepSubprogramDIE(
AddressesMap &RelocMgr, const DWARFDie &DIE, const DWARFFile &File,
CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo, unsigned Flags) { … }
unsigned DWARFLinker::shouldKeepDIE(AddressesMap &RelocMgr, const DWARFDie &DIE,
const DWARFFile &File, CompileUnit &Unit,
CompileUnit::DIEInfo &MyInfo,
unsigned Flags) { … }
static void updateChildIncompleteness(const DWARFDie &Die, CompileUnit &CU,
CompileUnit::DIEInfo &ChildInfo) { … }
static void updateRefIncompleteness(const DWARFDie &Die, CompileUnit &CU,
CompileUnit::DIEInfo &RefInfo) { … }
void DWARFLinker::lookForChildDIEsToKeep(
const DWARFDie &Die, CompileUnit &CU, unsigned Flags,
SmallVectorImpl<WorklistItem> &Worklist) { … }
static bool isODRCanonicalCandidate(const DWARFDie &Die, CompileUnit &CU) { … }
void DWARFLinker::markODRCanonicalDie(const DWARFDie &Die, CompileUnit &CU) { … }
void DWARFLinker::lookForRefDIEsToKeep(
const DWARFDie &Die, CompileUnit &CU, unsigned Flags,
const UnitListTy &Units, const DWARFFile &File,
SmallVectorImpl<WorklistItem> &Worklist) { … }
void DWARFLinker::lookForParentDIEsToKeep(
unsigned AncestorIdx, CompileUnit &CU, unsigned Flags,
SmallVectorImpl<WorklistItem> &Worklist) { … }
void DWARFLinker::lookForDIEsToKeep(AddressesMap &AddressesMap,
const UnitListTy &Units,
const DWARFDie &Die, const DWARFFile &File,
CompileUnit &Cu, unsigned Flags) { … }
#ifndef NDEBUG
struct BrokenLink {
BrokenLink(DWARFDie Parent, DWARFDie Child) : Parent(Parent), Child(Child) {}
DWARFDie Parent;
DWARFDie Child;
};
static void verifyKeepChain(CompileUnit &CU) {
std::vector<DWARFDie> Worklist;
Worklist.push_back(CU.getOrigUnit().getUnitDIE());
std::vector<BrokenLink> BrokenLinks;
while (!Worklist.empty()) {
const DWARFDie Current = Worklist.back();
Worklist.pop_back();
const bool CurrentDieIsKept = CU.getInfo(Current).Keep;
for (DWARFDie Child : reverse(Current.children())) {
Worklist.push_back(Child);
const bool ChildDieIsKept = CU.getInfo(Child).Keep;
if (!CurrentDieIsKept && ChildDieIsKept)
BrokenLinks.emplace_back(Current, Child);
}
}
if (!BrokenLinks.empty()) {
for (BrokenLink Link : BrokenLinks) {
WithColor::error() << formatv(
"Found invalid link in keep chain between {0:x} and {1:x}\n",
Link.Parent.getOffset(), Link.Child.getOffset());
errs() << "Parent:";
Link.Parent.dump(errs(), 0, {});
CU.getInfo(Link.Parent).dump();
errs() << "Child:";
Link.Child.dump(errs(), 2, {});
CU.getInfo(Link.Child).dump();
}
report_fatal_error("invalid keep chain");
}
}
#endif
void DWARFLinker::assignAbbrev(DIEAbbrev &Abbrev) { … }
unsigned DWARFLinker::DIECloner::cloneStringAttribute(DIE &Die,
AttributeSpec AttrSpec,
const DWARFFormValue &Val,
const DWARFUnit &U,
AttributesInfo &Info) { … }
unsigned DWARFLinker::DIECloner::cloneDieReferenceAttribute(
DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
unsigned AttrSize, const DWARFFormValue &Val, const DWARFFile &File,
CompileUnit &Unit) { … }
void DWARFLinker::DIECloner::cloneExpression(
DataExtractor &Data, DWARFExpression Expression, const DWARFFile &File,
CompileUnit &Unit, SmallVectorImpl<uint8_t> &OutputBuffer,
int64_t AddrRelocAdjustment, bool IsLittleEndian) { … }
unsigned DWARFLinker::DIECloner::cloneBlockAttribute(
DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
bool IsLittleEndian) { … }
unsigned DWARFLinker::DIECloner::cloneAddressAttribute(
DIE &Die, const DWARFDie &InputDIE, AttributeSpec AttrSpec,
unsigned AttrSize, const DWARFFormValue &Val, const CompileUnit &Unit,
AttributesInfo &Info) { … }
unsigned DWARFLinker::DIECloner::cloneScalarAttribute(
DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
CompileUnit &Unit, AttributeSpec AttrSpec, const DWARFFormValue &Val,
unsigned AttrSize, AttributesInfo &Info) { … }
unsigned DWARFLinker::DIECloner::cloneAttribute(
DIE &Die, const DWARFDie &InputDIE, const DWARFFile &File,
CompileUnit &Unit, const DWARFFormValue &Val, const AttributeSpec AttrSpec,
unsigned AttrSize, AttributesInfo &Info, bool IsLittleEndian) { … }
void DWARFLinker::DIECloner::addObjCAccelerator(CompileUnit &Unit,
const DIE *Die,
DwarfStringPoolEntryRef Name,
OffsetsStringPool &StringPool,
bool SkipPubSection) { … }
static bool
shouldSkipAttribute(bool Update,
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
bool SkipPC) { … }
struct AttributeLinkedOffsetFixup { … };
DIE *DWARFLinker::DIECloner::cloneDIE(const DWARFDie &InputDIE,
const DWARFFile &File, CompileUnit &Unit,
int64_t PCOffset, uint32_t OutOffset,
unsigned Flags, bool IsLittleEndian,
DIE *Die) { … }
void DWARFLinker::generateUnitRanges(CompileUnit &Unit, const DWARFFile &File,
DebugDieValuePool &AddrPool) const { … }
void DWARFLinker::DIECloner::generateUnitLocations(
CompileUnit &Unit, const DWARFFile &File,
ExpressionHandlerRef ExprHandler) { … }
static void patchAddrBase(DIE &Die, DIEInteger Offset) { … }
void DWARFLinker::DIECloner::emitDebugAddrSection(
CompileUnit &Unit, const uint16_t DwarfVersion) const { … }
static void insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
std::vector<DWARFDebugLine::Row> &Rows) { … }
static void patchStmtList(DIE &Die, DIEInteger Offset) { … }
void DWARFLinker::DIECloner::rememberUnitForMacroOffset(CompileUnit &Unit) { … }
void DWARFLinker::DIECloner::generateLineTableForUnit(CompileUnit &Unit) { … }
void DWARFLinker::emitAcceleratorEntriesForUnit(CompileUnit &Unit) { … }
void DWARFLinker::patchFrameInfoForObject(LinkContext &Context) { … }
uint32_t DWARFLinker::DIECloner::hashFullyQualifiedName(DWARFDie DIE,
CompileUnit &U,
const DWARFFile &File,
int ChildRecurseDepth) { … }
static uint64_t getDwoId(const DWARFDie &CUDie) { … }
static std::string
remapPath(StringRef Path,
const DWARFLinkerBase::ObjectPrefixMapTy &ObjectPrefixMap) { … }
static std::string
getPCMFile(const DWARFDie &CUDie,
const DWARFLinkerBase::ObjectPrefixMapTy *ObjectPrefixMap) { … }
std::pair<bool, bool> DWARFLinker::isClangModuleRef(const DWARFDie &CUDie,
std::string &PCMFile,
LinkContext &Context,
unsigned Indent,
bool Quiet) { … }
bool DWARFLinker::registerModuleReference(const DWARFDie &CUDie,
LinkContext &Context,
ObjFileLoaderTy Loader,
CompileUnitHandlerTy OnCUDieLoaded,
unsigned Indent) { … }
Error DWARFLinker::loadClangModule(
ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
LinkContext &Context, CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) { … }
uint64_t DWARFLinker::DIECloner::cloneAllCompileUnits(
DWARFContext &DwarfContext, const DWARFFile &File, bool IsLittleEndian) { … }
void DWARFLinker::copyInvariantDebugSection(DWARFContext &Dwarf) { … }
void DWARFLinker::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
CompileUnitHandlerTy OnCUDieLoaded) { … }
Error DWARFLinker::link() { … }
Error DWARFLinker::cloneModuleUnit(LinkContext &Context, RefModuleUnit &Unit,
DeclContextTree &ODRContexts,
OffsetsStringPool &DebugStrPool,
OffsetsStringPool &DebugLineStrPool,
DebugDieValuePool &StringOffsetPool,
unsigned Indent) { … }
void DWARFLinker::verifyInput(const DWARFFile &File) { … }
}