aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLai Wei-Chih <Robert.Lai@mediatek.com>2013-11-25 17:08:15 +0800
committerAndrew Hsieh <andrewhsieh@google.com>2015-03-24 11:54:25 -0700
commitab4504e2144956fafa7e23c66323b5f7dce2d488 (patch)
tree33975d58926777cee371b9b41ac354176c296cb1
parent6d1a6d60118b36d4823eb339f76a0f8108b5c9f5 (diff)
downloadllvm-ab4504e2144956fafa7e23c66323b5f7dce2d488.tar.gz
[ndk][pndk] Add bitcode strip tool ndk-strip.
-rw-r--r--tools/Makefile2
-rw-r--r--tools/ndk-strip/CMakeLists.txt15
-rw-r--r--tools/ndk-strip/Makefile14
-rw-r--r--tools/ndk-strip/ndk-strip.cpp211
4 files changed, 241 insertions, 1 deletions
diff --git a/tools/Makefile b/tools/Makefile
index 4667a79bf75..661b4891d0b 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -34,7 +34,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis llc llvm-ar llvm-nm llvm-link \
llvm-dwarfdump llvm-cov llvm-size llvm-stress llvm-mcmarkup \
llvm-profdata llvm-symbolizer obj2yaml yaml2obj llvm-c-test \
llvm-vtabledump verify-uselistorder dsymutil \
- ndk-link
+ ndk-link ndk-strip
# If Intel JIT Events support is configured, build an extra tool to test it.
ifeq ($(USE_INTEL_JITEVENTS), 1)
diff --git a/tools/ndk-strip/CMakeLists.txt b/tools/ndk-strip/CMakeLists.txt
new file mode 100644
index 00000000000..d6ab967865b
--- /dev/null
+++ b/tools/ndk-strip/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ asmparser
+ bitreader
+ bitwriter
+ codegen
+ instrumentation
+ ipo
+ irreader
+ linker
+ selectiondag
+ )
+
+add_llvm_tool(ndk-strip
+ ndk-strip.cpp
+ )
diff --git a/tools/ndk-strip/Makefile b/tools/ndk-strip/Makefile
new file mode 100644
index 00000000000..dae48e2a4c3
--- /dev/null
+++ b/tools/ndk-strip/Makefile
@@ -0,0 +1,14 @@
+LEVEL := ../..
+
+TOOLNAME = ndk-strip
+
+LINK_COMPONENTS := asmparser bitreader bitwriter codegen \
+ instrumentation ipo irreader linker selectiondag
+
+USEDLIBS := LLVMWrap.a
+
+# This tool has no plugins, optimize startup time.
+TOOL_NO_EXPORTS := 1
+
+include $(LEVEL)/Makefile.common
+
diff --git a/tools/ndk-strip/ndk-strip.cpp b/tools/ndk-strip/ndk-strip.cpp
new file mode 100644
index 00000000000..1a95244c520
--- /dev/null
+++ b/tools/ndk-strip/ndk-strip.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <cstdlib>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "llvm/Bitcode/BitcodeWriterPass.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/PassManager.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/SystemUtils.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Wrap/BitcodeWrapper.h"
+
+using namespace llvm;
+
+static cl::opt<std::string>
+InputFilename(cl::Positional, cl::desc("<input bitcode file>"),
+ cl::value_desc("filename"));
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool>
+Strip("strip-all", cl::desc("Strip all symbol info"));
+
+static cl::opt<bool>
+StripDebug("strip-debug", cl::desc("Strip debugger symbol info"));
+
+static cl::alias A0("s", cl::desc("Alias for --strip-all"),
+ cl::aliasopt(Strip));
+
+static cl::alias A1("S", cl::desc("Alias for --strip-debug"),
+ cl::aliasopt(StripDebug));
+
+static cl::alias A2("strip-unneeded", cl::desc("Alias for -strip-all"),
+ cl::aliasopt(Strip));
+
+
+static uint32_t ReadInt32(unsigned char *wrapper, size_t offset) {
+ uint32_t value = wrapper[offset] |
+ wrapper[offset+1] << 8 |
+ wrapper[offset+2] << 16 |
+ wrapper[offset+3] << 24;
+ return value;
+}
+
+static void WriteInt32(unsigned char *wrapper, unsigned offset, uint32_t value)
+{
+ wrapper[offset ] = value & 0x000000ff;
+ wrapper[offset+1] = (value & 0x0000ff00) >> 8;
+ wrapper[offset+2] = (value & 0x00ff0000) >> 16;
+ wrapper[offset+3] = (value & 0xff000000) >> 24;
+}
+
+static size_t ReadBitcodeWrapper(int input_fd, unsigned char **wrapper, size_t& bitcode_size) {
+ size_t buffer_size = 1024;
+ size_t fixed_field_size = 7*4;
+
+ *wrapper = (unsigned char*) calloc(1, buffer_size);
+ size_t nread = read(input_fd, (void*) *wrapper, fixed_field_size);
+
+ if (nread != fixed_field_size) {
+ errs() << "Could not read bitcode header\n";
+ exit(1);
+ }
+
+ if (!isBitcodeWrapper((const unsigned char *) *wrapper,
+ (const unsigned char *) *wrapper+fixed_field_size)) {
+ errs() << "Input file is not bitcode wrapper\n";
+ exit(0);
+ }
+
+ size_t offset_field = 2*4;
+ size_t size_field = 3*4;
+ size_t header_size = ReadInt32(*wrapper, offset_field);
+ bitcode_size = ReadInt32(*wrapper, size_field);
+
+ if (header_size > buffer_size) {
+ *wrapper = (unsigned char*) realloc((void *) *wrapper, header_size);
+ }
+
+ size_t variable_field_size = header_size-fixed_field_size;
+ if (variable_field_size > 0) {
+ nread = read(input_fd, (void*) ((*wrapper)+fixed_field_size), variable_field_size);
+ if (nread != (variable_field_size)) {
+ errs() << "Could not read bitcode header\n";
+ exit(1);
+ }
+ }
+
+ return header_size;
+}
+
+
+static void StripBitcode(const char *Bitcode, size_t BitcodeSize, std::string &BCString, LLVMContext &Context) {
+ StringRef input_data(Bitcode, BitcodeSize);
+ MemoryBufferRef buffer(input_data, "");
+
+ ErrorOr<Module*> Result = parseBitcodeFile(buffer, Context);
+ if (!Result) {
+ errs() << Result.getError().message() << '\n';
+ }
+
+ std::unique_ptr<Module> M(Result.get());
+ raw_string_ostream BCStream(BCString);
+
+ PassManager PM;
+
+ PM.add(createVerifierPass());
+ PM.add(new DataLayoutPass());
+
+ // Strip debug info and symbols.
+ if (Strip || StripDebug)
+ PM.add(createStripSymbolsPass(StripDebug && !Strip));
+
+ PM.add(createBitcodeWriterPass(BCStream));
+ PM.run(*M.get());
+ BCStream.flush();
+}
+
+int main(int argc, char **argv) {
+
+ sys::PrintStackTraceOnErrorSignal();
+ llvm::PrettyStackTraceProgram X(argc, argv);
+
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+ LLVMContext &Context = getGlobalContext();
+
+ cl::ParseCommandLineOptions(argc, argv, "Bitcode strip tool\n");
+
+ int input_fd = open(InputFilename.c_str(), O_RDONLY);
+
+ unsigned char *wrapper = NULL;
+ const char *bitcode = NULL;
+
+ // Read bitcode wrapper
+ size_t bitcode_size = 0;
+ size_t wrapper_size = ReadBitcodeWrapper(input_fd, &wrapper, bitcode_size);
+
+ // Read bitcode
+ bitcode = (const char*) calloc(1, bitcode_size);
+ size_t nread = read(input_fd, (void*) bitcode, bitcode_size);
+ if (nread != bitcode_size) {
+ errs() << "Could not read bitcode\n";
+ return 1;
+ }
+
+ // Strip bitcode
+ std::string BCString;
+ StripBitcode(bitcode, bitcode_size, BCString, Context);
+
+ // Update bitcode size
+ WriteInt32(wrapper, 12, BCString.length());
+
+ // Default to input filename
+ if (OutputFilename.empty())
+ OutputFilename = InputFilename;
+
+ // Output stripped bitcode
+ std::error_code EC;
+ tool_output_file Out(OutputFilename.c_str(), EC, sys::fs::F_None);
+ if (EC) {
+ errs() << EC.message() << '\n';
+ return 1;
+ }
+
+ Out.os().write((const char *) wrapper, wrapper_size);
+ Out.os().write(BCString.c_str(), BCString.length());
+ Out.keep();
+
+ // Clean up
+ free((void *) wrapper);
+ free((void *) bitcode);
+ close(input_fd);
+
+ return 0;
+}