typedef std::function<void(const Twine &Warning, StringRef Context,
const DWARFDie *DIE)>
messageHandler;
+typedef std::function<void(const DWARFFile &File)> inputVerificationHandler;
typedef std::function<ErrorOr<DWARFFile &>(StringRef ContainerName,
StringRef Path)>
objFileLoader;
Options.ErrorHandler = Handler;
}
+ /// Set verification handler which would be used to report verification
+ /// errors.
+ void setInputVerificationHandler(inputVerificationHandler Handler) {
+ Options.InputVerificationHandler = Handler;
+ }
+
/// Set map for Swift interfaces.
void setSwiftInterfacesMap(swiftInterfacesMap *Map) {
Options.ParseableSwiftInterfaces = Map;
};
/// Verify the given DWARF file.
- bool verify(const DWARFFile &File);
+ void verifyInput(const DWARFFile &File);
/// returns true if we need to translate strings.
bool needToTranslateStrings() { return StringsTranslator != nullptr; }
// error handler
messageHandler ErrorHandler = nullptr;
+ // input verification handler
+ inputVerificationHandler InputVerificationHandler = nullptr;
+
/// A list of all .swiftinterface files referenced by the debug
/// info, mapping Module name to path on disk. The entries need to
/// be uniqued and sorted and there are only few entries expected
continue;
if (Options.VerifyInputDWARF)
- verify(OptContext.File);
+ verifyInput(OptContext.File);
// Look for relocations that correspond to address map entries.
return Error::success();
}
-bool DWARFLinker::verify(const DWARFFile &File) {
+void DWARFLinker::verifyInput(const DWARFFile &File) {
assert(File.Dwarf);
raw_ostream &os = Options.Verbose ? errs() : nulls();
DIDumpOptions DumpOpts;
if (!File.Dwarf->verify(os, DumpOpts.noImplicitRecursion())) {
- reportWarning("input verification failed", File);
- return false;
+ if (Options.InputVerificationHandler)
+ Options.InputVerificationHandler(File);
}
- return true;
}
} // namespace llvm
[&](const Twine &Error, StringRef Context, const DWARFDie *) {
error(Error, Context);
});
+ GeneralLinker.setInputVerificationHandler([&](const DWARFFile &File) {
+ reportWarning("input verification failed", File.FileName);
+ HasVerificationErrors = true;
+ });
objFileLoader Loader = [&DebugMap, &RL,
this](StringRef ContainerName,
StringRef Path) -> ErrorOr<DWARFFile &> {
if (!Options.NoOutput && !ReflectionSectionsPresentInBinary) {
auto SectionToOffsetInDwarf =
calculateStartOfStrippableReflectionSections(Map);
- for (const auto &Obj : Map.objects())
+ for (const auto &Obj : Map.objects())
copySwiftReflectionMetadata(Obj.get(), Streamer.get(),
SectionToOffsetInDwarf, RelocationsToApply);
}
return Relocs.size() > 0;
}
-bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
- const DebugMap &DM, LinkOptions Options) {
- DwarfLinkerForBinary Linker(OutFile, BinHolder, std::move(Options));
- return Linker.link(DM);
-}
-
} // namespace dsymutil
} // namespace llvm
void reportWarning(const Twine &Warning, StringRef Context,
const DWARFDie *DIE = nullptr) const;
+ /// Returns true if input verification is enabled and verification errors were
+ /// found.
+ bool InputVerificationFailed() const { return HasVerificationErrors; }
+
/// Flags passed to DwarfLinker::lookForDIEsToKeep
enum TraversalFlags {
TF_Keep = 1 << 0, ///< Mark the traversed DIEs as kept.
bool ModuleCacheHintDisplayed = false;
bool ArchiveHintDisplayed = false;
+ bool HasVerificationErrors = false;
};
} // end namespace dsymutil
def verify_dwarf: Separate<["--", "-"], "verify-dwarf">,
MetaVarName<"<verification mode>">,
- HelpText<"Run the DWARF verifier on the input and/or output. Valid options are 'input', 'output', 'all' or 'none'.">,
+ HelpText<"Run the DWARF verifier on the input and/or output. "
+ "Valid options are 'none, 'input', 'output', 'all' or 'auto' "
+ "which runs the output verifier only if input verification passed.">,
Group<grp_general>;
def: Joined<["--", "-"], "verify-dwarf=">, Alias<verify_dwarf>;
#include "BinaryHolder.h"
#include "CFBundle.h"
#include "DebugMap.h"
+#include "DwarfLinkerForBinary.h"
#include "LinkUtils.h"
#include "MachOUtils.h"
#include "Reproducer.h"
None = 0,
Input = 1 << 0,
Output = 1 << 1,
+ OutputOnValidInput = 1 << 2,
All = Input | Output,
+ Auto = Input | OutputOnValidInput,
+#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
+ Default = Auto
+#else
+ Default = None
+#endif
};
inline bool flagIsSet(DWARFVerify Flags, DWARFVerify SingleFlag) {
std::vector<std::string> Archs;
std::vector<std::string> InputFiles;
unsigned NumThreads;
- DWARFVerify Verify = DWARFVerify::None;
+ DWARFVerify Verify = DWARFVerify::Default;
ReproducerMode ReproMode = ReproducerMode::GenerateOnCrash;
dsymutil::LinkOptions LinkOpts;
};
return DWARFVerify::Output;
if (S == "all")
return DWARFVerify::All;
+ if (S == "auto")
+ return DWARFVerify::Auto;
if (S == "none")
return DWARFVerify::None;
- return make_error<StringError>(
- "invalid verify type specified: '" + S +
- "'. Supported values are 'input', 'output', 'all' and 'none'.",
- inconvertibleErrorCode());
+ return make_error<StringError>("invalid verify type specified: '" + S +
+ "'. Supported values are 'none', "
+ "'input', 'output', 'all' and 'auto'.",
+ inconvertibleErrorCode());
}
- return DWARFVerify::None;
+ return DWARFVerify::Default;
}
/// Parses the command line options into the LinkOptions struct and performs
return Error::success();
}
-static bool verifyOutput(StringRef OutputFile, StringRef Arch, bool Verbose) {
+static bool verifyOutput(StringRef OutputFile, StringRef Arch,
+ DsymutilOptions Options) {
+
if (OutputFile == "-") {
WithColor::warning() << "verification skipped for " << Arch
- << "because writing to stdout.\n";
+ << " because writing to stdout.\n";
+ return true;
+ }
+
+ if (Options.LinkOpts.NoOutput) {
+ WithColor::warning() << "verification skipped for " << Arch
+ << " because --no-output was passed.\n";
return true;
}
Binary &Binary = *BinOrErr.get().getBinary();
if (auto *Obj = dyn_cast<MachOObjectFile>(&Binary)) {
- raw_ostream &os = Verbose ? errs() : nulls();
- os << "Verifying DWARF for architecture: " << Arch << "\n";
std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj);
+ if (DICtx->getMaxVersion() >= 5) {
+ WithColor::warning() << "verification skipped for " << Arch
+ << " because DWARFv5 is not fully supported yet.\n";
+ return true;
+ }
+ raw_ostream &os = Options.LinkOpts.Verbose ? errs() : nulls();
+ os << "Verifying DWARF for architecture: " << Arch << "\n";
DIDumpOptions DumpOpts;
bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion());
if (!success)
const bool NeedsTempFiles =
!Options.DumpDebugMap && (Options.OutputFile != "-") &&
(DebugMapPtrsOrErr->size() != 1 || Options.LinkOpts.Update);
- bool VerifyOutput = flagIsSet(Options.Verify, DWARFVerify::Output);
- if (VerifyOutput && Options.LinkOpts.NoOutput) {
- WithColor::warning()
- << "skipping output verification because --no-output was passed\n";
- VerifyOutput = false;
- }
// Set up a crash recovery context.
CrashRecoveryContext::Enable();
}
auto LinkLambda = [&,
- OutputFile](std::shared_ptr<raw_fd_ostream> Stream,
- LinkOptions Options) {
- AllOK.fetch_and(
- linkDwarf(*Stream, BinHolder, *Map, std::move(Options)));
+ OutputFile](std::shared_ptr<raw_fd_ostream> Stream) {
+ DwarfLinkerForBinary Linker(*Stream, BinHolder, Options.LinkOpts);
+ AllOK.fetch_and(Linker.link(*Map));
Stream->flush();
- if (VerifyOutput) {
+ if (flagIsSet(Options.Verify, DWARFVerify::Output) ||
+ (flagIsSet(Options.Verify, DWARFVerify::OutputOnValidInput) &&
+ !Linker.InputVerificationFailed())) {
AllOK.fetch_and(verifyOutput(
- OutputFile, Map->getTriple().getArchName(), Options.Verbose));
+ OutputFile, Map->getTriple().getArchName(), Options));
}
};
// out the (significantly smaller) stack when using threads. We don't
// want this limitation when we only have a single thread.
if (S.ThreadsRequested == 1)
- LinkLambda(OS, Options.LinkOpts);
+ LinkLambda(OS);
else
- Threads.async(LinkLambda, OS, Options.LinkOpts);
+ Threads.async(LinkLambda, OS);
}
Threads.wait();
StringRef InputFile, ArrayRef<std::string> Archs,
StringRef PrependPath = "");
-/// Link the Dwarf debug info as directed by the passed DebugMap \p DM into a
-/// DwarfFile named \p OutputFilename. \returns false if the link failed.
-bool linkDwarf(raw_fd_ostream &OutFile, BinaryHolder &BinHolder,
- const DebugMap &DM, LinkOptions Options);
-
} // end namespace dsymutil
} // end namespace llvm