aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2013-03-13 16:04:03 -0700
committerDerek Schuff <dschuff@chromium.org>2013-03-13 16:04:03 -0700
commitcb0dcd0adf5e43486154d143da30710fee0da301 (patch)
treead15b68cc4fc5765c130b5a0dba25d564a21404d /tools
parent79da56afe68a0c5b2c2227681014dd13705d78cc (diff)
ABI verifier: Add standalone tool pnacl-abicheck
This CL adds a standalone tool pnacl-abicheck for checking the ABI validity of a bitcode file. It also adds a flag pnaclabi-verify to llc to enable the same checking in llc. It also improves the mechanism for handling and reporting validation errors and uses it in both tools. R=jvoung@chromium.org,mseaborn@chromium.org BUG= https://code.google.com/p/nativeclient/issues/detail?id=2309 Review URL: https://codereview.chromium.org/12449014
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt1
-rw-r--r--tools/LLVMBuild.txt2
-rw-r--r--tools/Makefile2
-rw-r--r--tools/llc/llc.cpp41
-rw-r--r--tools/pnacl-abicheck/CMakeLists.txt5
-rw-r--r--tools/pnacl-abicheck/LLVMBuild.txt22
-rw-r--r--tools/pnacl-abicheck/Makefile16
-rw-r--r--tools/pnacl-abicheck/pnacl-abicheck.cpp60
8 files changed, 147 insertions, 2 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 144e8ec3ea..145645e3c0 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -42,6 +42,7 @@ add_subdirectory(llvm-stress)
add_subdirectory(llvm-mcmarkup)
add_subdirectory(llvm-symbolizer)
+add_subdirectory(pnacl-abicheck)
if( NOT WIN32 )
add_subdirectory(lto)
diff --git a/tools/LLVMBuild.txt b/tools/LLVMBuild.txt
index 25aa177b35..c887a4d9ad 100644
--- a/tools/LLVMBuild.txt
+++ b/tools/LLVMBuild.txt
@@ -16,7 +16,7 @@
;===------------------------------------------------------------------------===;
[common]
-subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup
+subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener llvm-link llvm-mc llvm-nm llvm-objdump llvm-prof llvm-ranlib llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup pnacl-abicheck
[component_0]
type = Group
diff --git a/tools/Makefile b/tools/Makefile
index cc1eea144f..38e79ab306 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -35,7 +35,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis \
llvm-diff macho-dump llvm-objdump llvm-readobj \
llvm-rtdyld llvm-dwarfdump llvm-cov \
llvm-size llvm-stress llvm-mcmarkup bc-wrap pso-stub \
- llvm-symbolizer
+ llvm-symbolizer pnacl-abicheck
# If Intel JIT Events support is configured, build an extra tool to test it.
ifeq ($(USE_INTEL_JITEVENTS), 1)
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index bdc14fc554..7294b3d347 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -15,6 +15,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/NaCl.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/DataStream.h" // @LOCALMOD
#include "llvm/CodeGen/CommandFlags.h"
@@ -107,6 +108,14 @@ ReduceMemoryFootprint("reduce-memory-footprint",
cl::desc("Aggressively reduce memory used by llc"),
cl::init(false));
+static cl::opt<bool>
+PNaClABIVerify("pnaclabi-verify",
+ cl::desc("Verify PNaCl bitcode ABI before translating"),
+ cl::init(false));
+static cl::opt<bool>
+PNaClABIVerifyFatalErrors("pnaclabi-verify-fatal-errors",
+ cl::desc("PNaCl ABI verification errors are fatal"),
+ cl::init(false));
// @LOCALMOD-END
// Determine optimization level.
@@ -307,6 +316,20 @@ int llc_main(int argc, char **argv) {
return 0;
}
+// @LOCALMOD-BEGIN
+static void CheckABIVerifyErrors(PNaClABIErrorReporter &Reporter,
+ const Twine &Name) {
+ if (PNaClABIVerify && Reporter.getErrorCount() > 0) {
+ errs() << (PNaClABIVerifyFatalErrors ? "ERROR:" : "WARNING:");
+ errs() << Name << " is not valid PNaCl bitcode:\n";
+ Reporter.printErrors(errs());
+ if (PNaClABIVerifyFatalErrors)
+ exit(1);
+ }
+ Reporter.reset();
+}
+// @LOCALMOD-END
+
static int compileModule(char **argv, LLVMContext &Context) {
// Load the module to be compiled...
SMDiagnostic Err;
@@ -317,6 +340,8 @@ static int compileModule(char **argv, LLVMContext &Context) {
bool SkipModule = MCPU == "help" ||
(!MAttrs.empty() && MAttrs.front() == "help");
+ PNaClABIErrorReporter ABIErrorReporter; // @LOCALMOD
+
// If user just wants to list available options, skip module loading
if (!SkipModule) {
// @LOCALMOD-BEGIN
@@ -346,6 +371,12 @@ static int compileModule(char **argv, LLVMContext &Context) {
}
// @LOCALMOD-BEGIN
+ if (PNaClABIVerify) {
+ // Verify the module (but not the functions yet)
+ ModulePass *VerifyPass = createPNaClABIVerifyModulePass(&ABIErrorReporter);
+ VerifyPass->runOnModule(*mod);
+ CheckABIVerifyErrors(ABIErrorReporter, "Module");
+ }
#if defined(__native_client__) && defined(NACL_SRPC)
RecordMetadataForSrpc(*mod);
@@ -472,6 +503,13 @@ static int compileModule(char **argv, LLVMContext &Context) {
PM.reset(new FunctionPassManager(mod));
else
PM.reset(new PassManager());
+
+ // Add the ABI verifier pass before the analysis and code emission passes.
+ FunctionPass *FunctionVerifyPass = NULL;
+ if (PNaClABIVerify) {
+ FunctionVerifyPass = createPNaClABIVerifyFunctionsPass(&ABIErrorReporter);
+ PM->add(FunctionVerifyPass);
+ }
// @LOCALMOD-END
// Add an appropriate TargetLibraryInfo pass for the module's triple.
@@ -506,6 +544,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
raw_fd_ostream ROS(GetObjectFileFD(), true);
ROS.SetBufferSize(1 << 20);
formatted_raw_ostream FOS(ROS);
+
// Ask the target to add backend passes as necessary.
if (Target.addPassesToEmitFile(*PM, FOS, FileType, NoVerify)) {
errs() << argv[0] << ": target does not support generation of this"
@@ -518,6 +557,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
P->doInitialization();
for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
P->run(*I);
+ CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
if (ReduceMemoryFootprint) {
I->Dematerialize();
}
@@ -570,6 +610,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
P->doInitialization();
for (Module::iterator I = mod->begin(), E = mod->end(); I != E; ++I) {
P->run(*I);
+ CheckABIVerifyErrors(ABIErrorReporter, "Function " + I->getName());
if (ReduceMemoryFootprint) {
I->Dematerialize();
}
diff --git a/tools/pnacl-abicheck/CMakeLists.txt b/tools/pnacl-abicheck/CMakeLists.txt
new file mode 100644
index 0000000000..d3296fa5a5
--- /dev/null
+++ b/tools/pnacl-abicheck/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS bitreader asmparser)
+
+add_llvm_tool(pnacl-abicheck
+ pnacl-abicheck.cc
+ )
diff --git a/tools/pnacl-abicheck/LLVMBuild.txt b/tools/pnacl-abicheck/LLVMBuild.txt
new file mode 100644
index 0000000000..0af322769c
--- /dev/null
+++ b/tools/pnacl-abicheck/LLVMBuild.txt
@@ -0,0 +1,22 @@
+;===- ./tools/pnacl-abicheck/LLVMBuild.txt ---------------------*- Conf -*--===;
+;
+; The LLVM Compiler Infrastructure
+;
+; This file is distributed under the University of Illinois Open Source
+; License. See LICENSE.TXT for details.
+;
+;===------------------------------------------------------------------------===;
+;
+; This is an LLVMBuild description file for the components in this subdirectory.
+;
+; For more information on the LLVMBuild system, please see:
+;
+; http://llvm.org/docs/LLVMBuild.html
+;
+;===------------------------------------------------------------------------===;
+
+[component_0]
+type = Tool
+name = pnacl-abicheck
+parent = Tools
+required_libraries = AsmParser BitReader
diff --git a/tools/pnacl-abicheck/Makefile b/tools/pnacl-abicheck/Makefile
new file mode 100644
index 0000000000..bd98690dd1
--- /dev/null
+++ b/tools/pnacl-abicheck/Makefile
@@ -0,0 +1,16 @@
+#===- tools/pnacl-abicheck/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL := ../..
+TOOLNAME := pnacl-abicheck
+LINK_COMPONENTS := bitreader asmparser
+
+include $(LEVEL)/Makefile.common
+
+
diff --git a/tools/pnacl-abicheck/pnacl-abicheck.cpp b/tools/pnacl-abicheck/pnacl-abicheck.cpp
new file mode 100644
index 0000000000..2bee788872
--- /dev/null
+++ b/tools/pnacl-abicheck/pnacl-abicheck.cpp
@@ -0,0 +1,60 @@
+//===-- pnacl-abicheck.cpp - Check PNaCl bitcode ABI ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tool checks files for compliance with the PNaCl bitcode ABI
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/Analysis/NaCl.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/IRReader.h"
+#include <string>
+
+using namespace llvm;
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
+
+static void CheckABIVerifyErrors(PNaClABIErrorReporter &Reporter,
+ const Twine &Name) {
+ if (Reporter.getErrorCount() > 0) {
+ errs() << "ERROR: " << Name << " is not valid PNaCl bitcode:\n";
+ Reporter.printErrors(errs());
+ }
+ Reporter.reset();
+}
+
+int main(int argc, char **argv) {
+ LLVMContext &Context = getGlobalContext();
+ SMDiagnostic Err;
+ OwningPtr<Module> Mod(ParseIRFile(InputFilename, Err, Context));
+ if (Mod.get() == 0) {
+ Err.print(argv[0], errs());
+ return 1;
+ }
+ PNaClABIErrorReporter ABIErrorReporter;
+ // Manually run the passes so we can tell the user which function had the
+ // error. No need for a pass manager since it's just one pass.
+ ModulePass *ModuleChecker = createPNaClABIVerifyModulePass(&ABIErrorReporter);
+ ModuleChecker->runOnModule(*Mod);
+ CheckABIVerifyErrors(ABIErrorReporter, "Module");
+ FunctionPass *FunctionChecker =
+ createPNaClABIVerifyFunctionsPass(&ABIErrorReporter);
+ for (Module::iterator MI = Mod->begin(), ME = Mod->end(); MI != ME; ++MI) {
+ FunctionChecker->runOnFunction(*MI);
+ CheckABIVerifyErrors(ABIErrorReporter, "Function " + MI->getName());
+ }
+
+ return 0;
+}