Currently, DWARFLinker determines the target DWARF version internally.
It examines incoming object files, detects maximal
DWARF version and uses that version for the output file.
This patch allows explicitly setting output DWARF version by the consumer
of DWARFLinker. So that DWARFLinker uses a specified version instead
of autodetected one. It allows consumers to use different logic for
setting the target DWARF version. f.e. instead of the maximally used version
someone could set a higher version to convert from DWARFv4 to DWARFv5
(This possibility is not supported yet, but it would be good if
the interface will support it). Or another variant is to set the target
version through the command line. In this patch, the autodetection is moved
into the consumers(DwarfLinkerForBinary.cpp, DebugInfoLinker.cpp).
Differential Revision: https://reviews.llvm.org/D132755
Options.ObjectPrefixMap = Map;
}
+ /// Set target DWARF version.
+ Error setTargetDWARFVersion(uint16_t TargetDWARFVersion) {
+ if (TargetDWARFVersion < 1 || TargetDWARFVersion > 5)
+ return createStringError(std::errc::invalid_argument,
+ "unsupported DWARF version: %d",
+ TargetDWARFVersion);
+
+ Options.TargetDWARFVersion = TargetDWARFVersion;
+ return Error::success();
+ }
+
private:
/// Flags passed to DwarfLinker::lookForDIEsToKeep
enum TraversalFlags {
Options.ErrorHandler(Warning, File.FileName, DIE);
}
- /// Remembers the oldest and newest DWARF version we've seen in a unit.
- void updateDwarfVersion(unsigned Version) {
- MaxDwarfVersion = std::max(MaxDwarfVersion, Version);
- MinDwarfVersion = std::min(MinDwarfVersion, Version);
- }
-
/// Remembers the kinds of accelerator tables we've seen in a unit.
void updateAccelKind(DWARFContext &Dwarf);
DwarfEmitter *TheDwarfEmitter;
std::vector<LinkContext> ObjectContexts;
- unsigned MaxDwarfVersion = 0;
- unsigned MinDwarfVersion = std::numeric_limits<unsigned>::max();
-
bool AtLeastOneAppleAccelTable = false;
bool AtLeastOneDwarfAccelTable = false;
/// linking options
struct DWARFLinkerOptions {
+ /// DWARF version for the output.
+ uint16_t TargetDWARFVersion = 0;
+
/// Generate processing log to the standard output.
bool Verbose = false;
std::unique_ptr<CompileUnit> Unit;
for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
OnCUDieLoaded(*CU);
- updateDwarfVersion(CU->getVersion());
// Recursively get all modules imported by this one.
auto ChildCUDie = CU->getUnitDIE();
if (!ChildCUDie)
Error DWARFLinker::link() {
assert(Options.NoOutput || TheDwarfEmitter);
+ assert((Options.TargetDWARFVersion != 0) &&
+ "TargetDWARFVersion should be set");
// First populate the data structure we need for each iteration of the
// parallel loop.
OptContext.File.Dwarf->getNumCompileUnits());
for (const auto &CU : OptContext.File.Dwarf->compile_units()) {
- updateDwarfVersion(CU->getVersion());
auto CUDie = CU->getUnitDIE(false);
if (Options.Verbose) {
outs() << "Input compilation unit:";
}
}
- // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
- if (MaxDwarfVersion == 0)
- MaxDwarfVersion = 3;
-
// At this point we know how much data we have emitted. We use this value to
// compare canonical DIE offsets in analyzeContextInfo to see if a definition
// is already emitted, without being affected by canonical die offsets set
return;
for (const auto &CU : Context.File.Dwarf->compile_units()) {
- updateDwarfVersion(CU->getVersion());
// The !isClangModuleRef condition effectively skips over fully resolved
// skeleton units.
auto CUDie = CU->getUnitDIE();
auto EmitLambda = [&]() {
// Emit everything that's global.
if (!Options.NoOutput) {
- TheDwarfEmitter->emitAbbrevs(Abbreviations, MaxDwarfVersion);
+ TheDwarfEmitter->emitAbbrevs(Abbreviations, Options.TargetDWARFVersion);
TheDwarfEmitter->emitStrings(OffsetsStringPool);
switch (Options.TheAccelTableKind) {
case DwarfLinkerAccelTableKind::None:
SectionToOffsetInDwarf, RelocationsToApply);
}
+ uint16_t MaxDWARFVersion = 0;
+ std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
+ [&MaxDWARFVersion](const DWARFUnit &Unit) {
+ MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
+ };
+
for (const auto &Obj : Map.objects()) {
// N_AST objects (swiftmodule files) should get dumped directly into the
// appropriate DWARF section.
}
if (auto ErrorOrObj = loadObject(*Obj, Map, RL))
- GeneralLinker.addObjectFile(*ErrorOrObj, Loader);
+ GeneralLinker.addObjectFile(*ErrorOrObj, Loader, OnCUDieLoaded);
else {
ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
Obj->getObjectFilename(), nullptr, nullptr,
}
}
+ // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
+ if (MaxDWARFVersion == 0)
+ MaxDWARFVersion = 3;
+
+ if (Error E = GeneralLinker.setTargetDWARFVersion(MaxDWARFVersion))
+ return error(toString(std::move(E)));
+
// link debug info for loaded object files.
if (Error E = GeneralLinker.link())
return error(toString(std::move(E)));
.str()))
return createStringError(std::errc::invalid_argument, "");
+ std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
+
+ uint16_t MaxDWARFVersion = 0;
+ std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
+ [&MaxDWARFVersion](const DWARFUnit &Unit) {
+ MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
+ };
+
// Create DWARF linker.
DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD);
std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1);
std::vector<std::string> EmptyWarnings;
- std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
-
// Unknown debug sections would be removed. Display warning
// for such sections.
for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
EmptyWarnings);
for (size_t I = 0; I < ObjectsForLinking.size(); I++)
- DebugInfoLinker.addObjectFile(*ObjectsForLinking[I]);
+ DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr,
+ OnCUDieLoaded);
+
+ // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
+ if (MaxDWARFVersion == 0)
+ MaxDWARFVersion = 3;
+
+ if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion))
+ return Err;
// Link debug info.
if (Error Err = DebugInfoLinker.link())