Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Unified Diff: tools/pnacl-hack-memset/pnacl-hack-memset.cpp

Issue 2262373002: Create one-off tool pnacl-hack-memset (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Fix comments as suggested in patch set 2. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/pnacl-hack-memset/Makefile ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/pnacl-hack-memset/pnacl-hack-memset.cpp
diff --git a/tools/pnacl-hack-memset/pnacl-hack-memset.cpp b/tools/pnacl-hack-memset/pnacl-hack-memset.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5cc891cd659e9d73eff663858552809661bc6243
--- /dev/null
+++ b/tools/pnacl-hack-memset/pnacl-hack-memset.cpp
@@ -0,0 +1,207 @@
+/* Copyright 2016 The Native Client Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can
+ * be found in the LICENSE file.
+ */
+
+//===-- pnacl-hack-memset.cpp - Fix (interim) Subzero bug -----------------===//
+//
+//===----------------------------------------------------------------------===//
+//
+// Fixes generated pexe's so that a Subzero bug (fixed but not yet fully
+// deployed until 10/2016). Does this by replacing calls to memset with a
+// constant (negative) byte value, and corresponding constant count arguments,
+// with a zero-add to the count. This causes the broken (and fixed) optimization
+// to not be fired.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/StreamingMemoryObject.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+using namespace llvm;
+
+namespace {
+
+cl::opt<std::string>
+OutputFilename("o", cl::desc("Specify fixed pexe filename"),
+ cl::value_desc("fixed pexe file"), cl::init("-"));
+
+cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<pexe file>"), cl::init("-"));
+
+cl::opt<bool>
+ShowFixes("show-fixes", cl::desc("Show fixes to memset"), cl::init(false));
+
+void WriteOutputFile(const Module *M) {
+
+ std::error_code EC;
+ std::unique_ptr<tool_output_file> Out(
+ new tool_output_file(OutputFilename, EC, sys::fs::F_None));
+ if (EC) {
+ errs() << EC.message() << '\n';
+ exit(1);
+ }
+
+ NaClWriteBitcodeToFile(M, Out->os(), /* AcceptSupportedOnly = */ false);
+
+ // Declare success.
+ Out->keep();
+}
+
+Module *readBitcode(std::string &Filename, LLVMContext &Context,
+ std::string &ErrorMessage) {
+ // Use the bitcode streaming interface
+ DataStreamer *Streamer = getDataFileStreamer(InputFilename, &ErrorMessage);
+ if (Streamer == nullptr)
+ return nullptr;
+ std::unique_ptr<StreamingMemoryObject> Buffer(
+ new StreamingMemoryObjectImpl(Streamer));
+ std::string DisplayFilename;
+ if (Filename == "-")
+ DisplayFilename = "<stdin>";
+ else
+ DisplayFilename = Filename;
+ DiagnosticHandlerFunction DiagnosticHandler = nullptr;
+ Module *M = getNaClStreamedBitcodeModule(
+ DisplayFilename, Buffer.release(), Context, DiagnosticHandler,
+ &ErrorMessage, /*AcceptSupportedOnly=*/false);
+ if (!M)
+ return nullptr;
+ if (std::error_code EC = M->materializeAllPermanently()) {
+ ErrorMessage = EC.message();
+ delete M;
+ return nullptr;
+ }
+ return M;
+}
+
+// Fixes the memset call if appropriate. Returns 1 if the Call to memset has
+// been fixed, and zero otherwise.
+size_t fixCallToMemset(CallInst *Call) {
+ if (Call->getNumArgOperands() != 5)
+ return 0;
+ Value *Val = Call->getArgOperand(1);
+ auto *CVal = dyn_cast<ConstantInt>(Val);
+ if (CVal == nullptr)
+ return 0;
+ if (!CVal->getType()->isIntegerTy(8))
+ return 0;
+ const APInt &IVal = CVal->getUniqueInteger();
+ if (!IVal.isNegative())
+ return 0;
+ Value *Count = Call->getArgOperand(2);
+ auto *CCount = dyn_cast<ConstantInt>(Count);
+ if (CCount == nullptr)
+ return 0;
+ if (!CCount->getType()->isIntegerTy(32))
+ return 0;
+ if (ShowFixes) {
+ Call->print(errs());
+ errs() << "\n-->\n";
+ }
+ auto *Zero = ConstantInt::getSigned(CCount->getType(), 0);
+ auto *Add = BinaryOperator::Create(Instruction::BinaryOps::Add, CCount, Zero);
+ auto *IAdd = dyn_cast<Instruction>(Add);
+ if (IAdd == nullptr)
+ return 0;
+ Call->setArgOperand(2, Add);
+ IAdd->insertBefore(Call);
+ if (ShowFixes) {
+ IAdd->print(errs());
+ errs() << "\n";
+ Call->print(errs());
+ errs() << "\n\n";
+ }
+ return 1;
+}
+
+// Fixes the instruction Inst, if it is a memset call that needs to be fixed.
+// Returns 1 if the instruction Inst has been fixed, and zero otherwise.
+size_t fixCallToMemset(Instruction *Inst) {
+ size_t Count = 0;
+ if (auto *Call = dyn_cast<CallInst>(Inst)) {
+ if (Function *Fcn = Call->getCalledFunction()) {
+ if ("llvm.memset.p0i8.i32" == Fcn->getName()) {
+ Count += fixCallToMemset(Call);
+ }
+ }
+ }
+ return Count;
+}
+
+// Fixes appropriate memset calls in the basic Block. Returns the number of
+// fixed memset calls in the given basic Block.
+size_t fixCallsToMemset(BasicBlock *Block) {
+ size_t Count = 0;
+ for (auto &Inst : *Block) {
+ Count += fixCallToMemset(&Inst);
+ }
+ return Count;
+}
+
+// Fixes appropriate memset calls in the function Fcn. Returns the number of
+// fixed memset calls for the given function.
+size_t fixCallsToMemset(Function *Fcn) {
+ size_t Count = 0;
+ for (auto &Block : *Fcn) {
+ Count += fixCallsToMemset(&Block);
+ }
+ return Count;
+}
+
+// Fixes appropriate memset calls in module M> Returns the number of fixed
+// memset calls.
+size_t fixCallsToMemset(Module *M) {
+ size_t ErrorCount = 0;
+ for (auto &Fcn : *M) {
+ if (!Fcn.isDeclaration())
+ ErrorCount += fixCallsToMemset(&Fcn);
+ }
+ return ErrorCount;
+}
+
+} // end of anonymous namespace
+
+int main(int argc, char **argv) {
+ // Print a stack trace if we signal out.
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ LLVMContext &Context = getGlobalContext();
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+ cl::ParseCommandLineOptions(
+ argc, argv, "Converts NaCl pexe wire format into LLVM bitcode format\n");
+
+ std::string ErrorMessage;
+ std::unique_ptr<Module> M(readBitcode(InputFilename, Context, ErrorMessage));
+
+ if (!M.get()) {
+ errs() << argv[0] << ": ";
+ if (ErrorMessage.size())
+ errs() << ErrorMessage << "\n";
+ else
+ errs() << "bitcode didn't read correctly.\n";
+ return 1;
+ }
+
+ size_t ErrorCount = fixCallsToMemset(M.get());
+ if (ErrorCount > 0) {
+ errs() << argv[0] << ": Fixed " << ErrorCount << " calls to memset.\n";
+ }
+
+ WriteOutputFile(M.get());
+ return 0;
+}
« no previous file with comments | « tools/pnacl-hack-memset/Makefile ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698