Index: test/tools/dsymutil/X86/verify.test =================================================================== --- /dev/null +++ test/tools/dsymutil/X86/verify.test @@ -0,0 +1,10 @@ +RUN: cat %p/../Inputs/basic.macho.x86_64 > %T/basic.macho.x86_64 +RUN: cat %p/../Inputs/basic-archive.macho.x86_64 > %T/basic-archive.macho.x86_64 +RUN: cat %p/../Inputs/basic-lto.macho.x86_64 > %T/basic-lto.macho.x86_64 +RUN: cat %p/../Inputs/basic-lto-dw4.macho.x86_64 > %T/basic-lto-dw4.macho.x86_64 + +# Multiple inputs in flat mode +RUN: not llvm-dsymutil -verify -f -oso-prepend-path=%p/.. %T/basic.macho.x86_64 %T/basic-archive.macho.x86_64 %T/basic-lto.macho.x86_64 %T/basic-lto-dw4.macho.x86_64 2>&1 | FileCheck %s + +CHECK: error: DIE has invalid DW_AT_location encoding: +CHECK: error: DIE has invalid DW_AT_location encoding: Index: test/tools/dsymutil/cmdline.test =================================================================== --- test/tools/dsymutil/cmdline.test +++ test/tools/dsymutil/cmdline.test @@ -14,6 +14,7 @@ HELP: -oso-prepend-path= HELP: -symtab HELP: -verbose +HELP: -verify HELP: -y HELP-NOT: -reverse-iterate Index: tools/dsymutil/dsymutil.cpp =================================================================== --- tools/dsymutil/dsymutil.cpp +++ 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); @@ -96,8 +101,8 @@ desc("Link DWARF debug information only for specified CPU architecture\n" "types. This option can be specified multiple times, once for each\n" "desired architecture. All CPU architectures will be linked by\n" - "default."), value_desc("arch"), - ZeroOrMore, cat(DsymCategory)); + "default."), + value_desc("arch"), ZeroOrMore, cat(DsymCategory)); static opt NoODR("no-odr", @@ -114,6 +119,9 @@ "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,30 @@ 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)) { + errs() << "Verifying DWARF for architecture: " << Arch << "\n"; + std::unique_ptr DICtx = DWARFContext::create(*Obj); + DIDumpOptions DumpOpts; + return DICtx->verify(errs(), DumpOpts.noImplicitRecursion()); + } + + return false; +} + static std::string getOutputFileName(llvm::StringRef InputFile) { if (FlatOut) { // If a flat dSYM has been requested, things are pretty simple. @@ -319,7 +351,6 @@ NumThreads = 1; NumThreads = std::min(NumThreads, DebugMapPtrsOrErr->size()); - // If there is more than one link to execute, we need to generate // temporary files. bool NeedsTempFiles = !DumpDebugMap && (*DebugMapPtrsOrErr).size() != 1; @@ -351,7 +382,7 @@ } else { std::error_code EC; OS = llvm::make_unique(NoOutput ? "-" : OutputFile, EC, - sys::fs::F_None); + sys::fs::F_None); if (EC) { errs() << OutputFile << ": " << EC.message(); return 1; @@ -361,6 +392,7 @@ 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,12 +408,15 @@ if (!AllOK) return 1; + if (Verify && !NoOutput && + !verify(OutputFile, Map->getTriple().getArchName())) + return 1; + if (NeedsTempFiles) TempFiles.emplace_back(Map->getTriple().getArchName().str(), OutputFile); } - if (NeedsTempFiles && !MachOUtils::generateUniversalBinary( TempFiles, getOutputFileName(InputFile), Options, SDKPath))