summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Prantl <aprantl@apple.com>2016-05-09 17:37:33 +0000
committerAdrian Prantl <aprantl@apple.com>2016-05-09 17:37:33 +0000
commit4a9292b127d520349ca66b3a3d232e795c1c2b1d (patch)
tree4e5f6fc469d31f571c35b4d974b5cf761bea88c6
parentc7b91e65d8960da9e9fb6a3d044f7da71d5879fa (diff)
downloadbcm5719-llvm-4a9292b127d520349ca66b3a3d232e795c1c2b1d.tar.gz
bcm5719-llvm-4a9292b127d520349ca66b3a3d232e795c1c2b1d.zip
Allow the LTO code generator to strip invalid debug info from the input.
This patch introduces a new option -lto-strip-invalid-debug-info, which drops malformed debug info from the input. The problem I'm trying to solve with this sequence of patches is that historically we've done a really bad job at verifying debug info. We want to be able to make the verifier stricter without having to worry about breaking bitcode compatibility with existing producers. For example, we don't necessarily want IR produced by an older version of clang to be rejected by an LTO link just because of malformed debug info, and rather provide an option to strip it. Note that merely outdated (but well-formed) debug info would continue to be auto-upgraded in this scenario. rdar://problem/25818489 http://reviews.llvm.org/D19987 llvm-svn: 268936
-rw-r--r--llvm/include/llvm/IR/Verifier.h14
-rw-r--r--llvm/lib/IR/Verifier.cpp10
-rw-r--r--llvm/lib/LTO/LTOCodeGenerator.cpp20
-rw-r--r--llvm/test/LTO/X86/Inputs/strip-debug-info.bcbin0 -> 852 bytes
-rw-r--r--llvm/test/LTO/X86/strip-debug-info.ll20
5 files changed, 57 insertions, 7 deletions
diff --git a/llvm/include/llvm/IR/Verifier.h b/llvm/include/llvm/IR/Verifier.h
index 41a47226caf..70bec787a4c 100644
--- a/llvm/include/llvm/IR/Verifier.h
+++ b/llvm/include/llvm/IR/Verifier.h
@@ -41,10 +41,16 @@ bool verifyFunction(const Function &F, raw_ostream *OS = nullptr);
/// \brief Check a module for errors.
///
-/// If there are no errors, the function returns false. If an error is found,
-/// a message describing the error is written to OS (if non-null) and true is
-/// returned.
-bool verifyModule(const Module &M, raw_ostream *OS = nullptr);
+/// If there are no errors, the function returns false. If an error is
+/// found, a message describing the error is written to OS (if
+/// non-null) and true is returned.
+///
+/// \return true if the module is broken. If BrokenDebugInfo is
+/// supplied, DebugInfo verification failures won't be considered as
+/// error and instead *BrokenDebugInfo will be set to true. Debug
+/// info errors can be "recovered" from by stripping the debug info.
+bool verifyModule(const Module &M, raw_ostream *OS = nullptr,
+ bool *BrokenDebugInfo = nullptr);
/// \brief Create a verifier pass.
///
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 576aefdf29a..e09f763f10b 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4417,18 +4417,22 @@ bool llvm::verifyFunction(const Function &f, raw_ostream *OS) {
return !V.verify(F);
}
-bool llvm::verifyModule(const Module &M, raw_ostream *OS) {
+bool llvm::verifyModule(const Module &M, raw_ostream *OS,
+ bool *BrokenDebugInfo) {
// Don't use a raw_null_ostream. Printing IR is expensive.
- Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/true);
+ Verifier V(OS, /*ShouldTreatBrokenDebugInfoAsError=*/!BrokenDebugInfo);
bool Broken = false;
for (const Function &F : M)
if (!F.isDeclaration() && !F.isMaterializable())
Broken |= !V.verify(F);
+ Broken |= !V.verify(M);
+ if (BrokenDebugInfo)
+ *BrokenDebugInfo = V.hasBrokenDebugInfo();
// Note that this function's return value is inverted from what you would
// expect of a function called "verify".
- return !V.verify(M) || Broken;
+ return Broken;
}
namespace {
diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp
index 226004a3353..0e1c46cff27 100644
--- a/llvm/lib/LTO/LTOCodeGenerator.cpp
+++ b/llvm/lib/LTO/LTOCodeGenerator.cpp
@@ -26,6 +26,7 @@
#include "llvm/Config/config.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
@@ -78,6 +79,16 @@ cl::opt<bool> LTODiscardValueNames(
cl::init(false),
#endif
cl::Hidden);
+
+cl::opt<bool> LTOStripInvalidDebugInfo(
+ "lto-strip-invalid-debug-info",
+ cl::desc("Strip invalid debug info metadata during LTO instead of aborting."),
+#ifdef NDEBUG
+ cl::init(true),
+#else
+ cl::init(false),
+#endif
+ cl::Hidden);
}
LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context)
@@ -488,6 +499,15 @@ void LTOCodeGenerator::verifyMergedModuleOnce() {
return;
HasVerifiedInput = true;
+ if (LTOStripInvalidDebugInfo) {
+ bool BrokenDebugInfo = false;
+ if (verifyModule(*MergedModule, &dbgs(), &BrokenDebugInfo))
+ report_fatal_error("Broken module found, compilation aborted!");
+ if (BrokenDebugInfo) {
+ emitWarning("Invalid debug info found, debug info will be stripped");
+ StripDebugInfo(*MergedModule);
+ }
+ }
if (verifyModule(*MergedModule, &dbgs()))
report_fatal_error("Broken module found, compilation aborted!");
}
diff --git a/llvm/test/LTO/X86/Inputs/strip-debug-info.bc b/llvm/test/LTO/X86/Inputs/strip-debug-info.bc
new file mode 100644
index 00000000000..c83195ff9ca
--- /dev/null
+++ b/llvm/test/LTO/X86/Inputs/strip-debug-info.bc
Binary files differ
diff --git a/llvm/test/LTO/X86/strip-debug-info.ll b/llvm/test/LTO/X86/strip-debug-info.ll
new file mode 100644
index 00000000000..265a34b9c97
--- /dev/null
+++ b/llvm/test/LTO/X86/strip-debug-info.ll
@@ -0,0 +1,20 @@
+; RUN: not llvm-lto -lto-strip-invalid-debug-info=false \
+; RUN: -o %t.o %S/Inputs/strip-debug-info.bc 2>&1 | \
+; RUN: FileCheck %s -allow-empty -check-prefix=CHECK-ERR
+; RUN: llvm-lto -lto-strip-invalid-debug-info=true -exported-symbol _foo \
+; RUN: -o %t.o %S/Inputs/strip-debug-info.bc 2>&1 | \
+; RUN: FileCheck %s -allow-empty -check-prefix=CHECK-WARN
+; RUN: llvm-nm %t.o | FileCheck %s
+
+; CHECK-ERR: Broken module found, compilation aborted
+; CHECK-WARN: Invalid debug info found, debug info will be stripped
+; CHECK: foo
+define void @foo() {
+ ret void
+}
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!1}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !DIFile(filename: "broken", directory: "")
OpenPOWER on IntegriCloud