From 5eb1a17437724e3c5eb8e8b5953a55e8e813c1a6 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Thu, 7 Dec 2017 11:17:19 +0000 Subject: [PATCH] [dsymutil] Add -verify option to run DWARF verifier after linking. This patch adds support for running the DWARF verifier on the linked debug info files. If the -verify options is specified and verification fails, dsymutil exists with abort with non-zero exit code. This behavior is *not* enabled by default. Differential revision: https://reviews.llvm.org/D40777 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320033 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/tools/dsymutil/X86/verify.test | 8 ++++++ test/tools/dsymutil/cmdline.test | 1 + tools/dsymutil/dsymutil.cpp | 41 +++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 test/tools/dsymutil/X86/verify.test diff --git a/test/tools/dsymutil/X86/verify.test b/test/tools/dsymutil/X86/verify.test new file mode 100644 index 00000000000..317edd06c9e --- /dev/null +++ b/test/tools/dsymutil/X86/verify.test @@ -0,0 +1,8 @@ +# Multiple inputs in flat mode +RUN: not llvm-dsymutil -verify -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 %p/../Inputs/basic-archive.macho.x86_64 %p/../Inputs/basic-lto.macho.x86_64 %p/../Inputs/basic-lto-dw4.macho.x86_64 -o %t 2>&1 | FileCheck %s --check-prefix=QUIET +RUN: not llvm-dsymutil -verify -verbose -oso-prepend-path=%p/.. %p/../Inputs/basic.macho.x86_64 %p/../Inputs/basic-archive.macho.x86_64 %p/../Inputs/basic-lto.macho.x86_64 %p/../Inputs/basic-lto-dw4.macho.x86_64 -o %t 2>&1 | FileCheck %s --check-prefix=QUIET --check-prefix=VERBOSE + +VERBOSE: Verifying DWARF for architecture: x86_64 +VERBOSE: error: DIE has invalid DW_AT_location encoding: +VERBOSE: error: DIE has invalid DW_AT_location encoding: +QUIET: error: verification failed diff --git a/test/tools/dsymutil/cmdline.test b/test/tools/dsymutil/cmdline.test index f66858e9ae5..89c296e1a9b 100644 --- a/test/tools/dsymutil/cmdline.test +++ b/test/tools/dsymutil/cmdline.test @@ -14,6 +14,7 @@ HELP: -o= HELP: -oso-prepend-path= HELP: -symtab HELP: -verbose +HELP: -verify HELP: -y HELP-NOT: -reverse-iterate diff --git a/tools/dsymutil/dsymutil.cpp b/tools/dsymutil/dsymutil.cpp index 5696f560217..fa5c6583bca 100644 --- a/tools/dsymutil/dsymutil.cpp +++ b/tools/dsymutil/dsymutil.cpp @@ -20,6 +20,10 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +#include "llvm/DebugInfo/DWARF/DWARFVerifier.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -40,6 +44,7 @@ using namespace llvm; using namespace llvm::cl; using namespace llvm::dsymutil; +using namespace object; static OptionCategory DsymCategory("Specific Options"); static opt Help("h", desc("Alias for -help"), Hidden); @@ -114,6 +119,9 @@ static opt InputIsYAMLDebugMap( "y", desc("Treat the input file is a YAML debug map rather than a binary."), init(false), cat(DsymCategory)); +static opt Verify("verify", desc("Verify the linked DWARF debug info."), + cat(DsymCategory)); + static bool createPlistFile(llvm::StringRef Bin, llvm::StringRef BundleRoot) { if (NoOutput) return true; @@ -184,6 +192,34 @@ static bool createBundleDir(llvm::StringRef BundleBase) { return true; } +static bool verify(llvm::StringRef OutputFile, llvm::StringRef Arch) { + if (OutputFile == "-") { + llvm::errs() << "warning: verification skipped for " << Arch + << "because writing to stdout.\n"; + return true; + } + + Expected> BinOrErr = createBinary(OutputFile); + if (!BinOrErr) { + errs() << OutputFile << ": " << toString(BinOrErr.takeError()); + return false; + } + + Binary &Binary = *BinOrErr.get().getBinary(); + if (auto *Obj = dyn_cast(&Binary)) { + raw_ostream &os = Verbose ? errs() : nulls(); + os << "Verifying DWARF for architecture: " << Arch << "\n"; + std::unique_ptr DICtx = DWARFContext::create(*Obj); + DIDumpOptions DumpOpts; + bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion()); + if (!success) + errs() << "error: verification failed for " << Arch << '\n'; + return success; + } + + return false; +} + static std::string getOutputFileName(llvm::StringRef InputFile) { if (FlatOut) { // If a flat dSYM has been requested, things are pretty simple. @@ -361,6 +397,7 @@ int main(int argc, char **argv) { std::atomic_char AllOK(1); auto LinkLambda = [&]() { AllOK.fetch_and(linkDwarf(*OS, *Map, Options)); + OS->flush(); }; // FIXME: The DwarfLinker can have some very deep recursion that can max @@ -376,6 +413,10 @@ int main(int argc, char **argv) { if (!AllOK) return 1; + if (Verify && !NoOutput && + !verify(OutputFile, Map->getTriple().getArchName())) + return 1; + if (NeedsTempFiles) TempFiles.emplace_back(Map->getTriple().getArchName().str(), OutputFile); -- 2.50.1