diff options
author | Derek Schuff <dschuff@chromium.org> | 2013-03-13 16:04:03 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2013-03-13 16:04:03 -0700 |
commit | cb0dcd0adf5e43486154d143da30710fee0da301 (patch) | |
tree | ad15b68cc4fc5765c130b5a0dba25d564a21404d /tools | |
parent | 79da56afe68a0c5b2c2227681014dd13705d78cc (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.txt | 1 | ||||
-rw-r--r-- | tools/LLVMBuild.txt | 2 | ||||
-rw-r--r-- | tools/Makefile | 2 | ||||
-rw-r--r-- | tools/llc/llc.cpp | 41 | ||||
-rw-r--r-- | tools/pnacl-abicheck/CMakeLists.txt | 5 | ||||
-rw-r--r-- | tools/pnacl-abicheck/LLVMBuild.txt | 22 | ||||
-rw-r--r-- | tools/pnacl-abicheck/Makefile | 16 | ||||
-rw-r--r-- | tools/pnacl-abicheck/pnacl-abicheck.cpp | 60 |
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; +} |