about summary refs log tree commit diff
path: root/llvm_mode
diff options
context:
space:
mode:
Diffstat (limited to 'llvm_mode')
-rw-r--r--llvm_mode/Makefile121
-rw-r--r--llvm_mode/README.laf-intel20
-rw-r--r--llvm_mode/README.llvm192
-rw-r--r--llvm_mode/afl-clang-fast.c381
-rw-r--r--llvm_mode/afl-llvm-pass.so.cc221
-rw-r--r--llvm_mode/afl-llvm-rt.o.c309
-rw-r--r--llvm_mode/compare-transform-pass.so.cc306
-rw-r--r--llvm_mode/split-compares-pass.so.cc527
-rw-r--r--llvm_mode/split-switches-pass.so.cc315
9 files changed, 2392 insertions, 0 deletions
diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile
new file mode 100644
index 00000000..13a53463
--- /dev/null
+++ b/llvm_mode/Makefile
@@ -0,0 +1,121 @@
+#
+# american fuzzy lop - LLVM instrumentation
+# -----------------------------------------
+#
+# Written by Laszlo Szekeres <lszekeres@google.com> and
+#            Michal Zalewski <lcamtuf@google.com>
+#
+# LLVM integration design comes from Laszlo Szekeres.
+#
+# Copyright 2015, 2016 Google Inc. All rights reserved.
+#
+# 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
+#
+
+PREFIX      ?= /usr/local
+HELPER_PATH  = $(PREFIX)/lib/afl
+BIN_PATH     = $(PREFIX)/bin
+
+VERSION     = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
+
+LLVM_CONFIG ?= llvm-config
+
+CFLAGS      ?= -O3 -funroll-loops
+CFLAGS      += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
+               -DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
+               -DVERSION=\"$(VERSION)\" 
+ifdef AFL_TRACE_PC
+  CFLAGS    += -DUSE_TRACE_PC=1
+endif
+
+CXXFLAGS    ?= -O3 -funroll-loops
+CXXFLAGS    += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
+               -DVERSION=\"$(VERSION)\" -Wno-variadic-macros
+
+CLANG_CFL    = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fpic $(CXXFLAGS)
+CLANG_LFL    = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
+
+# User teor2345 reports that this is required to make things work on MacOS X.
+
+ifeq "$(shell uname)" "Darwin"
+  CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
+endif
+
+# We were using llvm-config --bindir to get the location of clang, but
+# this seems to be busted on some distros, so using the one in $PATH is
+# probably better.
+
+ifeq "$(origin CC)" "default"
+  CC         = clang
+  CXX        = clang++
+endif
+
+ifndef AFL_TRACE_PC
+  PROGS      = ../afl-clang-fast ../afl-llvm-pass.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so
+else
+  PROGS      = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so
+endif
+
+all: test_deps $(PROGS) test_build all_done
+
+test_deps:
+ifndef AFL_TRACE_PC
+	@echo "[*] Checking for working 'llvm-config'..."
+	@which $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo "    (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
+else
+	@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
+endif
+	@echo "[*] Checking for working '$(CC)'..."
+	@which $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
+	@echo "[*] Checking for '../afl-showmap'..."
+	@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
+	@echo "[+] All set and ready to build."
+
+../afl-clang-fast: afl-clang-fast.c | test_deps
+	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
+	ln -sf afl-clang-fast ../afl-clang-fast++
+
+../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+
+# laf
+../split-switches-pass.so:	split-switches-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+../compare-transform-pass.so:	compare-transform-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+../split-compares-pass.so:	split-compares-pass.so.cc | test_deps
+	$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
+# /laf
+
+../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
+	$(CC) $(CFLAGS) -fPIC -c $< -o $@
+
+../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
+	@printf "[*] Building 32-bit variant of the runtime (-m32)... "
+	@$(CC) $(CFLAGS) -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+
+../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps
+	@printf "[*] Building 64-bit variant of the runtime (-m64)... "
+	@$(CC) $(CFLAGS) -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
+
+test_build: $(PROGS)
+	@echo "[*] Testing the CC wrapper and instrumentation output..."
+	unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
+	echo 0 | ../afl-showmap -m none -q -o .test-instr0 ./test-instr
+	echo 1 | ../afl-showmap -m none -q -o .test-instr1 ./test-instr
+	@rm -f test-instr
+	@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping <lcamtuf@google.com> to troubleshoot the issue."; echo; exit 1; fi
+	@echo "[+] All right, the instrumentation seems to be working!"
+
+all_done: test_build
+	@echo "[+] All done! You can now use '../afl-clang-fast' to compile programs."
+
+.NOTPARALLEL: clean
+
+clean:
+	rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 
+	rm -f $(PROGS) ../afl-clang-fast++
diff --git a/llvm_mode/README.laf-intel b/llvm_mode/README.laf-intel
new file mode 100644
index 00000000..891ab5fd
--- /dev/null
+++ b/llvm_mode/README.laf-intel
@@ -0,0 +1,20 @@
+Usage
+=====
+
+By default the passes will not run when you compile programs using 
+afl-clang-fast. Hence, you can use AFL as usual.
+To enable the passes you must set environment variables before you
+compile the target project.
+
+The following options exist:
+
+export LAF_SPLIT_SWITCHES=1     Enables the split-switches pass.
+
+export LAF_TRANSFORM_COMPARES=1 Enables the transform-compares pass
+                             (strcmp, memcmp, strncmp, strcasecmp, strncasecmp).
+
+export LAF_SPLIT_COMPARES=1     Enables the split-compares pass.
+      By default it will split all compares with a bit width <= 64 bits.
+      You can change this behaviour by setting 
+          export LAF_SPLIT_COMPARES_BITW=<bit_width>.
+
diff --git a/llvm_mode/README.llvm b/llvm_mode/README.llvm
new file mode 100644
index 00000000..761a820b
--- /dev/null
+++ b/llvm_mode/README.llvm
@@ -0,0 +1,192 @@
+============================================
+Fast LLVM-based instrumentation for afl-fuzz
+============================================
+
+  (See ../docs/README for the general instruction manual.)
+
+1) Introduction
+---------------
+
+!!! This works with LLVM up to version 6 !!!
+
+The code in this directory allows you to instrument programs for AFL using
+true compiler-level instrumentation, instead of the more crude
+assembly-level rewriting approach taken by afl-gcc and afl-clang. This has
+several interesting properties:
+
+  - The compiler can make many optimizations that are hard to pull off when
+    manually inserting assembly. As a result, some slow, CPU-bound programs will
+    run up to around 2x faster.
+
+    The gains are less pronounced for fast binaries, where the speed is limited
+    chiefly by the cost of creating new processes. In such cases, the gain will
+    probably stay within 10%.
+
+  - The instrumentation is CPU-independent. At least in principle, you should
+    be able to rely on it to fuzz programs on non-x86 architectures (after
+    building afl-fuzz with AFL_NO_X86=1).
+
+  - The instrumentation can cope a bit better with multi-threaded targets.
+
+  - Because the feature relies on the internals of LLVM, it is clang-specific
+    and will *not* work with GCC.
+
+Once this implementation is shown to be sufficiently robust and portable, it
+will probably replace afl-clang. For now, it can be built separately and
+co-exists with the original code.
+
+The idea and much of the implementation comes from Laszlo Szekeres.
+
+2) How to use
+-------------
+
+In order to leverage this mechanism, you need to have clang installed on your
+system. You should also make sure that the llvm-config tool is in your path
+(or pointed to via LLVM_CONFIG in the environment).
+
+Unfortunately, some systems that do have clang come without llvm-config or the
+LLVM development headers; one example of this is FreeBSD. FreeBSD users will
+also run into problems with clang being built statically and not being able to
+load modules (you'll see "Service unavailable" when loading afl-llvm-pass.so).
+
+To solve all your problems, you can grab pre-built binaries for your OS from:
+
+  http://llvm.org/releases/download.html
+
+...and then put the bin/ directory from the tarball at the beginning of your
+$PATH when compiling the feature and building packages later on. You don't need
+to be root for that.
+
+To build the instrumentation itself, type 'make'. This will generate binaries
+called afl-clang-fast and afl-clang-fast++ in the parent directory. Once this
+is done, you can instrument third-party code in a way similar to the standard
+operating mode of AFL, e.g.:
+
+  CC=/path/to/afl/afl-clang-fast ./configure [...options...]
+  make
+
+Be sure to also include CXX set to afl-clang-fast++ for C++ code.
+
+The tool honors roughly the same environmental variables as afl-gcc (see
+../docs/env_variables.txt). This includes AFL_INST_RATIO, AFL_USE_ASAN,
+AFL_HARDEN, and AFL_DONT_OPTIMIZE.
+
+Note: if you want the LLVM helper to be installed on your system for all
+users, you need to build it before issuing 'make install' in the parent
+directory.
+
+3) Gotchas, feedback, bugs
+--------------------------
+
+This is an early-stage mechanism, so field reports are welcome. You can send bug
+reports to <afl-users@googlegroups.com>.
+
+4) Bonus feature #1: deferred instrumentation
+---------------------------------------------
+
+AFL tries to optimize performance by executing the targeted binary just once,
+stopping it just before main(), and then cloning this "master" process to get
+a steady supply of targets to fuzz.
+
+Although this approach eliminates much of the OS-, linker- and libc-level
+costs of executing the program, it does not always help with binaries that
+perform other time-consuming initialization steps - say, parsing a large config
+file before getting to the fuzzed data.
+
+In such cases, it's beneficial to initialize the forkserver a bit later, once
+most of the initialization work is already done, but before the binary attempts
+to read the fuzzed input and parse it; in some cases, this can offer a 10x+
+performance gain. You can implement delayed initialization in LLVM mode in a
+fairly simple way.
+
+First, find a suitable location in the code where the delayed cloning can 
+take place. This needs to be done with *extreme* care to avoid breaking the
+binary. In particular, the program will probably malfunction if you select
+a location after:
+
+  - The creation of any vital threads or child processes - since the forkserver
+    can't clone them easily.
+
+  - The initialization of timers via setitimer() or equivalent calls.
+
+  - The creation of temporary files, network sockets, offset-sensitive file
+    descriptors, and similar shared-state resources - but only provided that
+    their state meaningfully influences the behavior of the program later on.
+
+  - Any access to the fuzzed input, including reading the metadata about its
+    size.
+
+With the location selected, add this code in the appropriate spot:
+
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+  __AFL_INIT();
+#endif
+
+You don't need the #ifdef guards, but including them ensures that the program
+will keep working normally when compiled with a tool other than afl-clang-fast.
+
+Finally, recompile the program with afl-clang-fast (afl-gcc or afl-clang will
+*not* generate a deferred-initialization binary) - and you should be all set!
+
+5) Bonus feature #2: persistent mode
+------------------------------------
+
+Some libraries provide APIs that are stateless, or whose state can be reset in
+between processing different input files. When such a reset is performed, a
+single long-lived process can be reused to try out multiple test cases,
+eliminating the need for repeated fork() calls and the associated OS overhead.
+
+The basic structure of the program that does this would be:
+
+  while (__AFL_LOOP(1000)) {
+
+    /* Read input data. */
+    /* Call library code to be fuzzed. */
+    /* Reset state. */
+
+  }
+
+  /* Exit normally */
+
+The numerical value specified within the loop controls the maximum number
+of iterations before AFL will restart the process from scratch. This minimizes
+the impact of memory leaks and similar glitches; 1000 is a good starting point,
+and going much higher increases the likelihood of hiccups without giving you
+any real performance benefits.
+
+A more detailed template is shown in ../experimental/persistent_demo/.
+Similarly to the previous mode, the feature works only with afl-clang-fast;
+#ifdef guards can be used to suppress it when using other compilers.
+
+Note that as with the previous mode, the feature is easy to misuse; if you
+do not fully reset the critical state, you may end up with false positives or
+waste a whole lot of CPU power doing nothing useful at all. Be particularly
+wary of memory leaks and of the state of file descriptors.
+
+PS. Because there are task switches still involved, the mode isn't as fast as
+"pure" in-process fuzzing offered, say, by LLVM's LibFuzzer; but it is a lot
+faster than the normal fork() model, and compared to in-process fuzzing,
+should be a lot more robust.
+
+6) Bonus feature #3: new 'trace-pc-guard' mode
+----------------------------------------------
+
+Recent versions of LLVM are shipping with a built-in execution tracing feature
+that provides AFL with the necessary tracing data without the need to
+post-process the assembly or install any compiler plugins. See:
+
+  http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards
+
+As of this writing, the feature is only available on SVN trunk, and is yet to
+make it to an official release of LLVM. Nevertheless, if you have a
+sufficiently recent compiler and want to give it a try, build afl-clang-fast
+this way:
+
+  AFL_TRACE_PC=1 make clean all
+
+Note that this mode is currently about 20% slower than "vanilla" afl-clang-fast,
+and about 5-10% slower than afl-clang. This is likely because the
+instrumentation is not inlined, and instead involves a function call. On systems
+that support it, compiling your target with -flto should help.
+
+
diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c
new file mode 100644
index 00000000..8aef68ef
--- /dev/null
+++ b/llvm_mode/afl-clang-fast.c
@@ -0,0 +1,381 @@
+/*
+   american fuzzy lop - LLVM-mode wrapper for clang
+   ------------------------------------------------
+
+   Written by Laszlo Szekeres <lszekeres@google.com> and
+              Michal Zalewski <lcamtuf@google.com>
+
+   LLVM integration design comes from Laszlo Szekeres.
+
+   Copyright 2015, 2016 Google Inc. All rights reserved.
+
+   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
+
+   This program is a drop-in replacement for clang, similar in most respects
+   to ../afl-gcc. It tries to figure out compilation mode, adds a bunch
+   of flags, and then calls the real compiler.
+
+ */
+
+#define AFL_MAIN
+
+#include "../config.h"
+#include "../types.h"
+#include "../debug.h"
+#include "../alloc-inl.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+static u8*  obj_path;               /* Path to runtime libraries         */
+static u8** cc_params;              /* Parameters passed to the real CC  */
+static u32  cc_par_cnt = 1;         /* Param count, including argv0      */
+
+
+/* Try to find the runtime libraries. If that fails, abort. */
+
+static void find_obj(u8* argv0) {
+
+  u8 *afl_path = getenv("AFL_PATH");
+  u8 *slash, *tmp;
+
+  if (afl_path) {
+
+    tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path);
+
+    if (!access(tmp, R_OK)) {
+      obj_path = afl_path;
+      ck_free(tmp);
+      return;
+    }
+
+    ck_free(tmp);
+
+  }
+
+  slash = strrchr(argv0, '/');
+
+  if (slash) {
+
+    u8 *dir;
+
+    *slash = 0;
+    dir = ck_strdup(argv0);
+    *slash = '/';
+
+    tmp = alloc_printf("%s/afl-llvm-rt.o", dir);
+
+    if (!access(tmp, R_OK)) {
+      obj_path = dir;
+      ck_free(tmp);
+      return;
+    }
+
+    ck_free(tmp);
+    ck_free(dir);
+
+  }
+
+  if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
+    obj_path = AFL_PATH;
+    return;
+  }
+
+  FATAL("Unable to find 'afl-llvm-rt.o' or 'afl-llvm-pass.so'. Please set AFL_PATH");
+ 
+}
+
+
+/* Copy argv to cc_params, making the necessary edits. */
+
+static void edit_params(u32 argc, char** argv) {
+
+  u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0;
+  u8 *name;
+
+  cc_params = ck_alloc((argc + 128) * sizeof(u8*));
+
+  name = strrchr(argv[0], '/');
+  if (!name) name = argv[0]; else name++;
+
+  if (!strcmp(name, "afl-clang-fast++")) {
+    u8* alt_cxx = getenv("AFL_CXX");
+    cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";
+  } else {
+    u8* alt_cc = getenv("AFL_CC");
+    cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";
+  }
+
+  /* There are two ways to compile afl-clang-fast. In the traditional mode, we
+     use afl-llvm-pass.so to inject instrumentation. In the experimental
+     'trace-pc-guard' mode, we use native LLVM instrumentation callbacks
+     instead. The latter is a very recent addition - see:
+
+     http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards */
+
+  // laf
+  if (getenv("LAF_SPLIT_SWITCHES")) {
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = "-load";
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = alloc_printf("%s/split-switches-pass.so", obj_path);
+  }
+
+  if (getenv("LAF_TRANSFORM_COMPARES")) {
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = "-load";
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = alloc_printf("%s/compare-transform-pass.so", obj_path);
+  }
+
+  if (getenv("LAF_SPLIT_COMPARES")) {
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = "-load";
+    cc_params[cc_par_cnt++] = "-Xclang";
+    cc_params[cc_par_cnt++] = alloc_printf("%s/split-compares-pass.so", obj_path);
+  }
+  // /laf
+
+#ifdef USE_TRACE_PC
+  cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+  cc_params[cc_par_cnt++] = "-mllvm";
+  cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0";
+#else
+  cc_params[cc_par_cnt++] = "-Xclang";
+  cc_params[cc_par_cnt++] = "-load";
+  cc_params[cc_par_cnt++] = "-Xclang";
+  cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path);
+#endif /* ^USE_TRACE_PC */
+
+  cc_params[cc_par_cnt++] = "-Qunused-arguments";
+
+  /* Detect stray -v calls from ./configure scripts. */
+
+  if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0;
+
+  while (--argc) {
+    u8* cur = *(++argv);
+
+    if (!strcmp(cur, "-m32")) bit_mode = 32;
+    if (!strcmp(cur, "-m64")) bit_mode = 64;
+
+    if (!strcmp(cur, "-x")) x_set = 1;
+
+    if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E"))
+      maybe_linking = 0;
+
+    if (!strcmp(cur, "-fsanitize=address") ||
+        !strcmp(cur, "-fsanitize=memory")) asan_set = 1;
+
+    if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
+
+    if (!strcmp(cur, "-shared")) maybe_linking = 0;
+
+    if (!strcmp(cur, "-Wl,-z,defs") ||
+        !strcmp(cur, "-Wl,--no-undefined")) continue;
+
+    cc_params[cc_par_cnt++] = cur;
+
+  }
+
+  if (getenv("AFL_HARDEN")) {
+
+    cc_params[cc_par_cnt++] = "-fstack-protector-all";
+
+    if (!fortify_set)
+      cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
+
+  }
+
+  if (!asan_set) {
+
+    if (getenv("AFL_USE_ASAN")) {
+
+      if (getenv("AFL_USE_MSAN"))
+        FATAL("ASAN and MSAN are mutually exclusive");
+
+      if (getenv("AFL_HARDEN"))
+        FATAL("ASAN and AFL_HARDEN are mutually exclusive");
+
+      cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
+      cc_params[cc_par_cnt++] = "-fsanitize=address";
+
+    } else if (getenv("AFL_USE_MSAN")) {
+
+      if (getenv("AFL_USE_ASAN"))
+        FATAL("ASAN and MSAN are mutually exclusive");
+
+      if (getenv("AFL_HARDEN"))
+        FATAL("MSAN and AFL_HARDEN are mutually exclusive");
+
+      cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
+      cc_params[cc_par_cnt++] = "-fsanitize=memory";
+
+    }
+
+  }
+
+#ifdef USE_TRACE_PC
+
+  if (getenv("AFL_INST_RATIO"))
+    FATAL("AFL_INST_RATIO not available at compile time with 'trace-pc'.");
+
+#endif /* USE_TRACE_PC */
+
+  if (!getenv("AFL_DONT_OPTIMIZE")) {
+
+    cc_params[cc_par_cnt++] = "-g";
+    cc_params[cc_par_cnt++] = "-O3";
+    cc_params[cc_par_cnt++] = "-funroll-loops";
+
+  }
+
+  if (getenv("AFL_NO_BUILTIN")) {
+
+    cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
+    cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
+    cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
+    cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
+    cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
+
+  }
+
+  cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
+  cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
+  cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
+
+  /* When the user tries to use persistent or deferred forkserver modes by
+     appending a single line to the program, we want to reliably inject a
+     signature into the binary (to be picked up by afl-fuzz) and we want
+     to call a function from the runtime .o file. This is unnecessarily
+     painful for three reasons:
+
+     1) We need to convince the compiler not to optimize out the signature.
+        This is done with __attribute__((used)).
+
+     2) We need to convince the linker, when called with -Wl,--gc-sections,
+        not to do the same. This is done by forcing an assignment to a
+        'volatile' pointer.
+
+     3) We need to declare __afl_persistent_loop() in the global namespace,
+        but doing this within a method in a class is hard - :: and extern "C"
+        are forbidden and __attribute__((alias(...))) doesn't work. Hence the
+        __asm__ aliasing trick.
+
+   */
+
+  cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)="
+    "({ static volatile char *_B __attribute__((used)); "
+    " _B = (char*)\"" PERSIST_SIG "\"; "
+#ifdef __APPLE__
+    "__attribute__((visibility(\"default\"))) "
+    "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
+#else
+    "__attribute__((visibility(\"default\"))) "
+    "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
+#endif /* ^__APPLE__ */
+    "_L(_A); })";
+
+  cc_params[cc_par_cnt++] = "-D__AFL_INIT()="
+    "do { static volatile char *_A __attribute__((used)); "
+    " _A = (char*)\"" DEFER_SIG "\"; "
+#ifdef __APPLE__
+    "__attribute__((visibility(\"default\"))) "
+    "void _I(void) __asm__(\"___afl_manual_init\"); "
+#else
+    "__attribute__((visibility(\"default\"))) "
+    "void _I(void) __asm__(\"__afl_manual_init\"); "
+#endif /* ^__APPLE__ */
+    "_I(); } while (0)";
+
+  if (maybe_linking) {
+
+    if (x_set) {
+      cc_params[cc_par_cnt++] = "-x";
+      cc_params[cc_par_cnt++] = "none";
+    }
+
+    switch (bit_mode) {
+
+      case 0:
+        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path);
+        break;
+
+      case 32:
+        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path);
+
+        if (access(cc_params[cc_par_cnt - 1], R_OK))
+          FATAL("-m32 is not supported by your compiler");
+
+        break;
+
+      case 64:
+        cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path);
+
+        if (access(cc_params[cc_par_cnt - 1], R_OK))
+          FATAL("-m64 is not supported by your compiler");
+
+        break;
+
+    }
+
+  }
+
+  cc_params[cc_par_cnt] = NULL;
+
+}
+
+
+/* Main entry point */
+
+int main(int argc, char** argv) {
+
+  if (isatty(2) && !getenv("AFL_QUIET")) {
+
+#ifdef USE_TRACE_PC
+    SAYF(cCYA "afl-clang-fast [tpcg] " cBRI VERSION  cRST " by <lszekeres@google.com>\n");
+#else
+    SAYF(cCYA "afl-clang-fast " cBRI VERSION  cRST " by <lszekeres@google.com>\n");
+#endif /* ^USE_TRACE_PC */
+
+  }
+
+  if (argc < 2) {
+
+    SAYF("\n"
+         "This is a helper application for afl-fuzz. It serves as a drop-in replacement\n"
+         "for clang, letting you recompile third-party code with the required runtime\n"
+         "instrumentation. A common use pattern would be one of the following:\n\n"
+
+         "  CC=%s/afl-clang-fast ./configure\n"
+         "  CXX=%s/afl-clang-fast++ ./configure\n\n"
+
+         "In contrast to the traditional afl-clang tool, this version is implemented as\n"
+         "an LLVM pass and tends to offer improved performance with slow programs.\n\n"
+
+         "You can specify custom next-stage toolchain via AFL_CC and AFL_CXX. Setting\n"
+         "AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
+         BIN_PATH, BIN_PATH);
+
+    exit(1);
+
+  }
+
+
+  find_obj(argv[0]);
+
+  edit_params(argc, argv);
+
+  execvp(cc_params[0], (char**)cc_params);
+
+  FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
+
+  return 0;
+
+}
diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc
new file mode 100644
index 00000000..b02c072f
--- /dev/null
+++ b/llvm_mode/afl-llvm-pass.so.cc
@@ -0,0 +1,221 @@
+/*
+   american fuzzy lop - LLVM-mode instrumentation pass
+   ---------------------------------------------------
+
+   Written by Laszlo Szekeres <lszekeres@google.com> and
+              Michal Zalewski <lcamtuf@google.com>
+
+   LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
+   from afl-as.c are Michal's fault.
+
+   Copyright 2015, 2016 Google Inc. All rights reserved.
+
+   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
+
+   This library is plugged into LLVM when invoking clang through afl-clang-fast.
+   It tells the compiler to add code roughly equivalent to the bits discussed
+   in ../afl-as.h.
+
+ */
+
+#define AFL_LLVM_PASS
+
+#include "../config.h"
+#include "../debug.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/CFG.h"
+#include <algorithm>
+
+using namespace llvm;
+
+namespace {
+
+  class AFLCoverage : public ModulePass {
+
+    public:
+
+      static char ID;
+      AFLCoverage() : ModulePass(ID) { }
+
+      bool runOnModule(Module &M) override;
+
+      // StringRef getPassName() const override {
+      //  return "American Fuzzy Lop Instrumentation";
+      // }
+
+  };
+
+}
+
+
+char AFLCoverage::ID = 0;
+
+
+bool AFLCoverage::runOnModule(Module &M) {
+
+  LLVMContext &C = M.getContext();
+
+  IntegerType *Int8Ty  = IntegerType::getInt8Ty(C);
+  IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
+  unsigned int cur_loc = 0;
+
+  /* Show a banner */
+
+  char be_quiet = 0;
+
+  if (isatty(2) && !getenv("AFL_QUIET")) {
+
+    SAYF(cCYA "afl-llvm-pass " cBRI VERSION cRST " by <lszekeres@google.com>\n");
+
+  } else be_quiet = 1;
+
+  /* Decide instrumentation ratio */
+
+  char* inst_ratio_str = getenv("AFL_INST_RATIO");
+  unsigned int inst_ratio = 100;
+
+  if (inst_ratio_str) {
+
+    if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
+        inst_ratio > 100)
+      FATAL("Bad value of AFL_INST_RATIO (must be between 1 and 100)");
+
+  }
+
+  /* Get globals for the SHM region and the previous location. Note that
+     __afl_prev_loc is thread-local. */
+
+  GlobalVariable *AFLMapPtr =
+      new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
+                         GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
+
+  GlobalVariable *AFLPrevLoc = new GlobalVariable(
+      M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc",
+      0, GlobalVariable::GeneralDynamicTLSModel, 0, false);
+
+  /* Instrument all the things! */
+
+  int inst_blocks = 0;
+
+  for (auto &F : M)
+    for (auto &BB : F) {
+
+      BasicBlock::iterator IP = BB.getFirstInsertionPt();
+      IRBuilder<> IRB(&(*IP));
+
+      if (AFL_R(100) >= inst_ratio) continue;
+
+      /* Make up cur_loc */
+
+       //cur_loc++;
+      cur_loc = AFL_R(MAP_SIZE);
+
+      // only instrument if this basic block is the destination of a previous
+      // basic block that has multiple successors
+      // this gets rid of ~5-10% of instrumentations that are unnecessary
+      // result: a little more speed and less map pollution
+      int more_than_one = -1;
+      //fprintf(stderr, "BB %u: ", cur_loc);
+      for (BasicBlock *Pred : predecessors(&BB)) {
+        int count = 0;
+        if (more_than_one == -1)
+          more_than_one = 0;
+        //fprintf(stderr, " %p=>", Pred);
+        for (BasicBlock *Succ : successors(Pred)) {
+          //if (count > 0)
+          //  fprintf(stderr, "|");
+          if (Succ != NULL) count++;
+          //fprintf(stderr, "%p", Succ);
+        }
+        if (count > 1)
+          more_than_one = 1;
+      }
+      //fprintf(stderr, " == %d\n", more_than_one);
+      if (more_than_one != 1)
+        continue;
+
+      ConstantInt *CurLoc = ConstantInt::get(Int32Ty, cur_loc);
+
+      /* Load prev_loc */
+
+      LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
+      PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+      Value *PrevLocCasted = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
+
+      /* Load SHM pointer */
+
+      LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
+      MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+      Value *MapPtrIdx =
+          IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocCasted, CurLoc));
+
+      /* Update bitmap */
+
+      LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
+      Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+      Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
+      IRB.CreateStore(Incr, MapPtrIdx)
+          ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+
+      /* Set prev_loc to cur_loc >> 1 */
+
+      StoreInst *Store =
+          IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1), AFLPrevLoc);
+      Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
+
+      inst_blocks++;
+
+    }
+
+  /* Say something nice. */
+
+  if (!be_quiet) {
+
+    if (!inst_blocks) WARNF("No instrumentation targets found.");
+    else OKF("Instrumented %u locations (%s mode, ratio %u%%).",
+             inst_blocks, getenv("AFL_HARDEN") ? "hardened" :
+             ((getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) ?
+              "ASAN/MSAN" : "non-hardened"), inst_ratio);
+
+  }
+
+  return true;
+
+}
+
+
+static void registerAFLPass(const PassManagerBuilder &,
+                            legacy::PassManagerBase &PM) {
+
+  PM.add(new AFLCoverage());
+
+}
+
+
+static RegisterStandardPasses RegisterAFLPass(
+    PassManagerBuilder::EP_OptimizerLast, registerAFLPass);
+
+static RegisterStandardPasses RegisterAFLPass0(
+    PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);
diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c
new file mode 100644
index 00000000..342dcc90
--- /dev/null
+++ b/llvm_mode/afl-llvm-rt.o.c
@@ -0,0 +1,309 @@
+/*
+   american fuzzy lop - LLVM instrumentation bootstrap
+   ---------------------------------------------------
+
+   Written by Laszlo Szekeres <lszekeres@google.com> and
+              Michal Zalewski <lcamtuf@google.com>
+
+   LLVM integration design comes from Laszlo Szekeres.
+
+   Copyright 2015, 2016 Google Inc. All rights reserved.
+
+   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
+
+   This code is the rewrite of afl-as.h's main_payload.
+
+*/
+
+#include "../config.h"
+#include "../types.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/mman.h>
+#include <sys/shm.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+
+/* This is a somewhat ugly hack for the experimental 'trace-pc-guard' mode.
+   Basically, we need to make sure that the forkserver is initialized after
+   the LLVM-generated runtime initialization pass, not before. */
+
+#ifdef USE_TRACE_PC
+#  define CONST_PRIO 5
+#else
+#  define CONST_PRIO 0
+#endif /* ^USE_TRACE_PC */
+
+
+/* Globals needed by the injected instrumentation. The __afl_area_initial region
+   is used for instrumentation output before __afl_map_shm() has a chance to run.
+   It will end up as .comm, so it shouldn't be too wasteful. */
+
+u8  __afl_area_initial[MAP_SIZE];
+u8* __afl_area_ptr = __afl_area_initial;
+
+__thread u32 __afl_prev_loc;
+
+
+/* Running in persistent mode? */
+
+static u8 is_persistent;
+
+
+/* SHM setup. */
+
+static void __afl_map_shm(void) {
+
+  u8 *id_str = getenv(SHM_ENV_VAR);
+
+  /* If we're running under AFL, attach to the appropriate region, replacing the
+     early-stage __afl_area_initial region that is needed to allow some really
+     hacky .init code to work correctly in projects such as OpenSSL. */
+
+  if (id_str) {
+
+    u32 shm_id = atoi(id_str);
+
+    __afl_area_ptr = shmat(shm_id, NULL, 0);
+
+    /* Whooooops. */
+
+    if (__afl_area_ptr == (void *)-1) _exit(1);
+
+    /* Write something into the bitmap so that even with low AFL_INST_RATIO,
+       our parent doesn't give up on us. */
+
+    __afl_area_ptr[0] = 1;
+
+  }
+
+}
+
+
+/* Fork server logic. */
+
+static void __afl_start_forkserver(void) {
+
+  static u8 tmp[4];
+  s32 child_pid;
+
+  u8  child_stopped = 0;
+  
+  void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
+
+  /* Phone home and tell the parent that we're OK. If parent isn't there,
+     assume we're not running in forkserver mode and just execute program. */
+
+  if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
+
+  while (1) {
+
+    u32 was_killed;
+    int status;
+
+    /* Wait for parent by reading from the pipe. Abort if read fails. */
+
+    if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
+
+    /* If we stopped the child in persistent mode, but there was a race
+       condition and afl-fuzz already issued SIGKILL, write off the old
+       process. */
+
+    if (child_stopped && was_killed) {
+      child_stopped = 0;
+      if (waitpid(child_pid, &status, 0) < 0) _exit(1);
+    }
+
+    if (!child_stopped) {
+
+      /* Once woken up, create a clone of our process. */
+
+      child_pid = fork();
+      if (child_pid < 0) _exit(1);
+
+      /* In child process: close fds, resume execution. */
+
+      if (!child_pid) {
+        signal(SIGCHLD, old_sigchld_handler);
+
+        close(FORKSRV_FD);
+        close(FORKSRV_FD + 1);
+        return;
+  
+      }
+
+    } else {
+
+      /* Special handling for persistent mode: if the child is alive but
+         currently stopped, simply restart it with SIGCONT. */
+
+      kill(child_pid, SIGCONT);
+      child_stopped = 0;
+
+    }
+
+    /* In parent process: write PID to pipe, then wait for child. */
+
+    if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1);
+
+    if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0)
+      _exit(1);
+
+    /* In persistent mode, the child stops itself with SIGSTOP to indicate
+       a successful run. In this case, we want to wake it up without forking
+       again. */
+
+    if (WIFSTOPPED(status)) child_stopped = 1;
+
+    /* Relay wait status to pipe, then loop back. */
+
+    if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1);
+
+  }
+
+}
+
+
+/* A simplified persistent mode handler, used as explained in README.llvm. */
+
+int __afl_persistent_loop(unsigned int max_cnt) {
+
+  static u8  first_pass = 1;
+  static u32 cycle_cnt;
+
+  if (first_pass) {
+
+    /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
+       On subsequent calls, the parent will take care of that, but on the first
+       iteration, it's our job to erase any trace of whatever happened
+       before the loop. */
+
+    if (is_persistent) {
+
+      memset(__afl_area_ptr, 0, MAP_SIZE);
+      __afl_area_ptr[0] = 1;
+      __afl_prev_loc = 0;
+    }
+
+    cycle_cnt  = max_cnt;
+    first_pass = 0;
+    return 1;
+
+  }
+
+  if (is_persistent) {
+
+    if (--cycle_cnt) {
+
+      raise(SIGSTOP);
+
+      __afl_area_ptr[0] = 1;
+      __afl_prev_loc = 0;
+
+      return 1;
+
+    } else {
+
+      /* When exiting __AFL_LOOP(), make sure that the subsequent code that
+         follows the loop is not traced. We do that by pivoting back to the
+         dummy output region. */
+
+      __afl_area_ptr = __afl_area_initial;
+
+    }
+
+  }
+
+  return 0;
+
+}
+
+
+/* This one can be called from user code when deferred forkserver mode
+    is enabled. */
+
+void __afl_manual_init(void) {
+
+  static u8 init_done;
+
+  if (!init_done) {
+
+    __afl_map_shm();
+    __afl_start_forkserver();
+    init_done = 1;
+
+  }
+
+}
+
+
+/* Proper initialization routine. */
+
+__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
+
+  is_persistent = !!getenv(PERSIST_ENV_VAR);
+
+  if (getenv(DEFER_ENV_VAR)) return;
+
+  __afl_manual_init();
+
+}
+
+
+/* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard.
+   It remains non-operational in the traditional, plugin-backed LLVM mode.
+   For more info about 'trace-pc-guard', see README.llvm.
+
+   The first function (__sanitizer_cov_trace_pc_guard) is called back on every
+   edge (as opposed to every basic block). */
+
+void __sanitizer_cov_trace_pc_guard(uint32_t* guard) {
+  __afl_area_ptr[*guard]++;
+}
+
+
+/* Init callback. Populates instrumentation IDs. Note that we're using
+   ID of 0 as a special value to indicate non-instrumented bits. That may
+   still touch the bitmap, but in a fairly harmless way. */
+
+void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop) {
+
+  u32 inst_ratio = 100;
+  u8* x;
+
+  if (start == stop || *start) return;
+
+  x = getenv("AFL_INST_RATIO");
+  if (x) inst_ratio = atoi(x);
+
+  if (!inst_ratio || inst_ratio > 100) {
+    fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n");
+    abort();
+  }
+
+  /* Make sure that the first element in the range is always set - we use that
+     to avoid duplicate calls (which can happen as an artifact of the underlying
+     implementation in LLVM). */
+
+  *(start++) = R(MAP_SIZE - 1) + 1;
+
+  while (start < stop) {
+
+    if (R(100) < inst_ratio) *start = R(MAP_SIZE - 1) + 1;
+    else *start = 0;
+
+    start++;
+
+  }
+
+}
diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc
new file mode 100644
index 00000000..acca3ff0
--- /dev/null
+++ b/llvm_mode/compare-transform-pass.so.cc
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2016 laf-intel
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/Analysis/ValueTracking.h"
+
+#include <set>
+
+using namespace llvm;
+
+namespace {
+
+  class CompareTransform : public ModulePass {
+
+    public:
+      static char ID;
+      CompareTransform() : ModulePass(ID) {
+      } 
+
+      bool runOnModule(Module &M) override;
+
+#if __clang_major__ < 4
+      const char * getPassName() const override {
+#else
+      StringRef getPassName() const override {
+#endif
+        return "transforms compare functions";
+      }
+    private:
+      bool transformCmps(Module &M, const bool processStrcmp, const bool processMemcmp
+        ,const bool processStrncmp, const bool processStrcasecmp, const bool processStrncasecmp);
+  };
+}
+
+
+char CompareTransform::ID = 0;
+
+bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, const bool processMemcmp
+  , const bool processStrncmp, const bool processStrcasecmp, const bool processStrncasecmp) {
+
+  std::vector<CallInst*> calls;
+  LLVMContext &C = M.getContext();
+  IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
+  IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
+  IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
+  Constant* c = M.getOrInsertFunction("tolower",
+                                         Int32Ty,
+                                         Int32Ty
+#if __clang_major__ < 7
+					 , nullptr
+#endif
+					 );
+  Function* tolowerFn = cast<Function>(c);
+
+  /* iterate over all functions, bbs and instruction and add suitable calls to strcmp/memcmp/strncmp/strcasecmp/strncasecmp */
+  for (auto &F : M) {
+    for (auto &BB : F) {
+      for(auto &IN: BB) {
+        CallInst* callInst = nullptr;
+
+        if ((callInst = dyn_cast<CallInst>(&IN))) {
+
+          bool isStrcmp      = processStrcmp;
+          bool isMemcmp      = processMemcmp;
+          bool isStrncmp     = processStrncmp;
+          bool isStrcasecmp  = processStrcasecmp;
+          bool isStrncasecmp = processStrncasecmp;
+
+          Function *Callee = callInst->getCalledFunction();
+          if (!Callee)
+            continue;
+          if (callInst->getCallingConv() != llvm::CallingConv::C)
+            continue;
+          StringRef FuncName = Callee->getName();
+          isStrcmp      &= !FuncName.compare(StringRef("strcmp"));
+          isMemcmp      &= !FuncName.compare(StringRef("memcmp"));
+          isStrncmp     &= !FuncName.compare(StringRef("strncmp"));
+          isStrcasecmp  &= !FuncName.compare(StringRef("strcasecmp"));
+          isStrncasecmp &= !FuncName.compare(StringRef("strncasecmp"));
+
+          if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp && !isStrncasecmp)
+            continue;
+
+          /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function prototype */
+          FunctionType *FT = Callee->getFunctionType();
+
+
+          isStrcmp      &= FT->getNumParams() == 2 &&
+                      FT->getReturnType()->isIntegerTy(32) &&
+                      FT->getParamType(0) == FT->getParamType(1) &&
+                      FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+          isStrcasecmp  &= FT->getNumParams() == 2 &&
+                      FT->getReturnType()->isIntegerTy(32) &&
+                      FT->getParamType(0) == FT->getParamType(1) &&
+                      FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext());
+          isMemcmp      &= FT->getNumParams() == 3 &&
+                      FT->getReturnType()->isIntegerTy(32) &&
+                      FT->getParamType(0)->isPointerTy() &&
+                      FT->getParamType(1)->isPointerTy() &&
+                      FT->getParamType(2)->isIntegerTy();
+          isStrncmp     &= FT->getNumParams() == 3 &&
+                      FT->getReturnType()->isIntegerTy(32) &&
+                      FT->getParamType(0) == FT->getParamType(1) &&
+                      FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext()) &&
+                      FT->getParamType(2)->isIntegerTy();
+          isStrncasecmp &= FT->getNumParams() == 3 &&
+                      FT->getReturnType()->isIntegerTy(32) &&
+                      FT->getParamType(0) == FT->getParamType(1) &&
+                      FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext()) &&
+                      FT->getParamType(2)->isIntegerTy();
+
+          if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp && !isStrncasecmp)
+            continue;
+
+          /* is a str{n,}{case,}cmp/memcmp, check is we have
+           * str{case,}cmp(x, "const") or str{case,}cmp("const", x)
+           * strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x, ..)
+           * memcmp(x, "const", ..) or memcmp("const", x, ..) */
+          Value *Str1P = callInst->getArgOperand(0), *Str2P = callInst->getArgOperand(1);
+          StringRef Str1, Str2;
+          bool HasStr1 = getConstantStringInfo(Str1P, Str1);
+          bool HasStr2 = getConstantStringInfo(Str2P, Str2);
+
+          /* handle cases of one string is const, one string is variable */
+          if (!(HasStr1 ^ HasStr2))
+            continue;
+
+          if (isMemcmp || isStrncmp || isStrncasecmp) {
+            /* check if third operand is a constant integer
+             * strlen("constStr") and sizeof() are treated as constant */
+            Value *op2 = callInst->getArgOperand(2);
+            ConstantInt* ilen = dyn_cast<ConstantInt>(op2);
+            if (!ilen)
+              continue;
+            /* final precaution: if size of compare is larger than constant string skip it*/
+            uint64_t literalLength = HasStr1 ? GetStringLength(Str1P) : GetStringLength(Str2P);
+            if (literalLength < ilen->getZExtValue())
+              continue;
+          }
+
+          calls.push_back(callInst);
+        }
+      }
+    }
+  }
+
+  if (!calls.size())
+    return false;
+  errs() << "Replacing " << calls.size() << " calls to strcmp/memcmp/strncmp/strcasecmp/strncasecmp\n";
+
+  for (auto &callInst: calls) {
+
+    Value *Str1P = callInst->getArgOperand(0), *Str2P = callInst->getArgOperand(1);
+    StringRef Str1, Str2, ConstStr;
+    Value *VarStr;
+    bool HasStr1 = getConstantStringInfo(Str1P, Str1);
+    getConstantStringInfo(Str2P, Str2);
+    uint64_t constLen, sizedLen;
+    bool isMemcmp          = !callInst->getCalledFunction()->getName().compare(StringRef("memcmp"));
+    bool isSizedcmp        = isMemcmp
+		          || !callInst->getCalledFunction()->getName().compare(StringRef("strncmp"))
+		          || !callInst->getCalledFunction()->getName().compare(StringRef("strncasecmp"));
+    bool isCaseInsensitive = !callInst->getCalledFunction()->getName().compare(StringRef("strcasecmp"))
+		          || !callInst->getCalledFunction()->getName().compare(StringRef("strncasecmp"));
+
+    if (isSizedcmp) {
+      Value *op2 = callInst->getArgOperand(2);
+      ConstantInt* ilen = dyn_cast<ConstantInt>(op2);
+      sizedLen = ilen->getZExtValue();
+    }
+
+    if (HasStr1) {
+      ConstStr = Str1;
+      VarStr = Str2P;
+      constLen = isMemcmp ? sizedLen : GetStringLength(Str1P);
+    }
+    else {
+      ConstStr = Str2;
+      VarStr = Str1P;
+      constLen = isMemcmp ? sizedLen : GetStringLength(Str2P);
+    }
+    if (isSizedcmp && constLen > sizedLen) {
+      constLen = sizedLen;
+    }
+
+    errs() << callInst->getCalledFunction()->getName() << ": len " << constLen << ": " << ConstStr << "\n";
+
+    /* split before the call instruction */
+    BasicBlock *bb = callInst->getParent();
+    BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
+    BasicBlock *next_bb =  BasicBlock::Create(C, "cmp_added", end_bb->getParent(), end_bb);
+    BranchInst::Create(end_bb, next_bb);
+    PHINode *PN = PHINode::Create(Int32Ty, constLen + 1, "cmp_phi");
+
+    TerminatorInst *term = bb->getTerminator();
+    BranchInst::Create(next_bb, bb);
+    term->eraseFromParent();
+
+    for (uint64_t i = 0; i < constLen; i++) {
+
+      BasicBlock *cur_bb = next_bb;
+
+      char c = isCaseInsensitive ? tolower(ConstStr[i]) : ConstStr[i];
+
+
+      BasicBlock::iterator IP = next_bb->getFirstInsertionPt();
+      IRBuilder<> IRB(&*IP);
+
+      Value* v = ConstantInt::get(Int64Ty, i);
+      Value *ele  = IRB.CreateInBoundsGEP(VarStr, v, "empty");
+      Value *load = IRB.CreateLoad(ele);
+      if (isCaseInsensitive) {
+        // load >= 'A' && load <= 'Z' ? load | 0x020 : load
+        std::vector<Value *> args;
+        args.push_back(load);
+        load = IRB.CreateCall(tolowerFn, args, "tmp");
+      }
+      Value *isub;
+      if (HasStr1)
+        isub = IRB.CreateSub(ConstantInt::get(Int8Ty, c), load);
+      else
+        isub = IRB.CreateSub(load, ConstantInt::get(Int8Ty, c));
+
+      Value *sext = IRB.CreateSExt(isub, Int32Ty); 
+      PN->addIncoming(sext, cur_bb);
+
+
+      if (i < constLen - 1) {
+        next_bb =  BasicBlock::Create(C, "cmp_added", end_bb->getParent(), end_bb);
+        BranchInst::Create(end_bb, next_bb);
+
+        TerminatorInst *term = cur_bb->getTerminator();
+        Value *icmp = IRB.CreateICmpEQ(isub, ConstantInt::get(Int8Ty, 0));
+        IRB.CreateCondBr(icmp, next_bb, end_bb);
+        term->eraseFromParent();
+      } else {
+        //IRB.CreateBr(end_bb);
+      }
+
+      //add offset to varstr
+      //create load
+      //create signed isub
+      //create icmp
+      //create jcc
+      //create next_bb
+    }
+
+    /* since the call is the first instruction of the bb it is safe to
+     * replace it with a phi instruction */
+    BasicBlock::iterator ii(callInst);
+    ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN);
+  }
+
+
+  return true;
+}
+
+bool CompareTransform::runOnModule(Module &M) {
+
+  llvm::errs() << "Running compare-transform-pass by laf.intel@gmail.com, extended by heiko@hexco.de\n";
+  transformCmps(M, true, true, true, true, true);
+  verifyModule(M);
+
+  return true;
+}
+
+static void registerCompTransPass(const PassManagerBuilder &,
+                            legacy::PassManagerBase &PM) {
+
+  auto p = new CompareTransform();
+  PM.add(p);
+
+}
+
+static RegisterStandardPasses RegisterCompTransPass(
+    PassManagerBuilder::EP_OptimizerLast, registerCompTransPass);
+
+static RegisterStandardPasses RegisterCompTransPass0(
+    PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass);
+
diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc
new file mode 100644
index 00000000..5bd01d62
--- /dev/null
+++ b/llvm_mode/split-compares-pass.so.cc
@@ -0,0 +1,527 @@
+/*
+ * Copyright 2016 laf-intel
+ *
+ * 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 "llvm/Pass.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IR/Module.h"
+
+#include "llvm/IR/IRBuilder.h"
+
+using namespace llvm;
+
+namespace {
+  class SplitComparesTransform : public ModulePass {
+    public:
+      static char ID;
+      SplitComparesTransform() : ModulePass(ID) {}
+
+      bool runOnModule(Module &M) override;
+#if __clang_major__ >= 4
+      StringRef getPassName() const override {
+#else
+      const char * getPassName() const override {
+#endif
+        return "simplifies and splits ICMP instructions";
+      }
+    private:
+      bool splitCompares(Module &M, unsigned bitw);
+      bool simplifyCompares(Module &M);
+      bool simplifySignedness(Module &M);
+
+  };
+}
+
+char SplitComparesTransform::ID = 0;
+
+/* This function splits ICMP instructions with xGE or xLE predicates into two 
+ * ICMP instructions with predicate xGT or xLT and EQ */
+bool SplitComparesTransform::simplifyCompares(Module &M) {
+  LLVMContext &C = M.getContext();
+  std::vector<Instruction*> icomps;
+  IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
+
+  /* iterate over all functions, bbs and instruction and add
+   * all integer comparisons with >= and <= predicates to the icomps vector */
+  for (auto &F : M) {
+    for (auto &BB : F) {
+      for (auto &IN: BB) {
+        CmpInst* selectcmpInst = nullptr;
+
+        if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
+
+          if (selectcmpInst->getPredicate() != CmpInst::ICMP_UGE &&
+              selectcmpInst->getPredicate() != CmpInst::ICMP_SGE &&
+              selectcmpInst->getPredicate() != CmpInst::ICMP_ULE &&
+              selectcmpInst->getPredicate() != CmpInst::ICMP_SLE ) {
+            continue;
+          }
+
+          auto op0 = selectcmpInst->getOperand(0);
+          auto op1 = selectcmpInst->getOperand(1);
+
+          IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+          IntegerType* intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+
+          /* this is probably not needed but we do it anyway */
+          if (!intTyOp0 || !intTyOp1) {
+            continue;
+          }
+
+          icomps.push_back(selectcmpInst);
+        }
+      }
+    }
+  }
+
+  if (!icomps.size()) {
+    return false;
+  }
+
+
+  for (auto &IcmpInst: icomps) {
+    BasicBlock* bb = IcmpInst->getParent();
+
+    auto op0 = IcmpInst->getOperand(0);
+    auto op1 = IcmpInst->getOperand(1);
+
+    /* find out what the new predicate is going to be */
+    auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate();
+    CmpInst::Predicate new_pred;
+    switch(pred) {
+      case CmpInst::ICMP_UGE:
+        new_pred = CmpInst::ICMP_UGT;
+        break;
+      case CmpInst::ICMP_SGE:
+        new_pred = CmpInst::ICMP_SGT;
+        break;
+      case CmpInst::ICMP_ULE:
+        new_pred = CmpInst::ICMP_ULT;
+        break;
+      case CmpInst::ICMP_SLE:
+        new_pred = CmpInst::ICMP_SLT;
+        break;
+      default: // keep the compiler happy
+        continue;
+    }
+
+    /* split before the icmp instruction */
+    BasicBlock* end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
+
+    /* the old bb now contains a unconditional jump to the new one (end_bb)
+     * we need to delete it later */
+
+    /* create the ICMP instruction with new_pred and add it to the old basic
+     * block bb it is now at the position where the old IcmpInst was */
+    Instruction* icmp_np;
+    icmp_np = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_np);
+
+    /* create a new basic block which holds the new EQ icmp */
+    Instruction *icmp_eq;
+    /* insert middle_bb before end_bb */
+    BasicBlock* middle_bb =  BasicBlock::Create(C, "injected",
+      end_bb->getParent(), end_bb);
+    icmp_eq = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, op0, op1);
+    middle_bb->getInstList().push_back(icmp_eq);
+    /* add an unconditional branch to the end of middle_bb with destination
+     * end_bb */
+    BranchInst::Create(end_bb, middle_bb);
+
+    /* replace the uncond branch with a conditional one, which depends on the
+     * new_pred icmp. True goes to end, false to the middle (injected) bb */
+    auto term = bb->getTerminator();
+    BranchInst::Create(end_bb, middle_bb, icmp_np, bb);
+    term->eraseFromParent();
+
+
+    /* replace the old IcmpInst (which is the first inst in end_bb) with a PHI
+     * inst to wire up the loose ends */
+    PHINode *PN = PHINode::Create(Int1Ty, 2, "");
+    /* the first result depends on the outcome of icmp_eq */
+    PN->addIncoming(icmp_eq, middle_bb);
+    /* if the source was the original bb we know that the icmp_np yielded true
+     * hence we can hardcode this value */
+    PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
+    /* replace the old IcmpInst with our new and shiny PHI inst */
+    BasicBlock::iterator ii(IcmpInst);
+    ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+  }
+
+  return true;
+}
+
+/* this function transforms signed compares to equivalent unsigned compares */
+bool SplitComparesTransform::simplifySignedness(Module &M) {
+  LLVMContext &C = M.getContext();
+  std::vector<Instruction*> icomps;
+  IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
+
+  /* iterate over all functions, bbs and instruction and add
+   * all signed compares to icomps vector */
+  for (auto &F : M) {
+    for (auto &BB : F) {
+      for(auto &IN: BB) {
+        CmpInst* selectcmpInst = nullptr;
+
+        if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
+
+          if (selectcmpInst->getPredicate() != CmpInst::ICMP_SGT &&
+             selectcmpInst->getPredicate() != CmpInst::ICMP_SLT
+             ) {
+            continue;
+          }
+
+          auto op0 = selectcmpInst->getOperand(0);
+          auto op1 = selectcmpInst->getOperand(1);
+
+          IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+          IntegerType* intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+
+          /* see above */
+          if (!intTyOp0 || !intTyOp1) {
+            continue;
+          }
+
+          /* i think this is not possible but to lazy to look it up */
+          if (intTyOp0->getBitWidth() != intTyOp1->getBitWidth()) {
+            continue;
+          }
+
+          icomps.push_back(selectcmpInst);
+        }
+      }
+    }
+  }
+
+  if (!icomps.size()) {
+    return false;
+  }
+
+  for (auto &IcmpInst: icomps) {
+    BasicBlock* bb = IcmpInst->getParent();
+
+    auto op0 = IcmpInst->getOperand(0);
+    auto op1 = IcmpInst->getOperand(1);
+
+    IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+    unsigned bitw = intTyOp0->getBitWidth();
+    IntegerType *IntType = IntegerType::get(C, bitw);
+
+
+    /* get the new predicate */
+    auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate();
+    CmpInst::Predicate new_pred;
+    if (pred == CmpInst::ICMP_SGT) {
+      new_pred = CmpInst::ICMP_UGT;
+    } else {
+      new_pred = CmpInst::ICMP_ULT;
+    }
+
+    BasicBlock* end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
+
+    /* create a 1 bit compare for the sign bit. to do this shift and trunc
+     * the original operands so only the first bit remains.*/
+    Instruction *s_op0, *t_op0, *s_op1, *t_op1, *icmp_sign_bit;
+
+    s_op0 = BinaryOperator::Create(Instruction::LShr, op0, ConstantInt::get(IntType, bitw - 1));
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op0);
+    t_op0 = new TruncInst(s_op0, Int1Ty);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), t_op0);
+
+    s_op1 = BinaryOperator::Create(Instruction::LShr, op1, ConstantInt::get(IntType, bitw - 1));
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op1);
+    t_op1 = new TruncInst(s_op1, Int1Ty);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), t_op1);
+
+    /* compare of the sign bits */
+    icmp_sign_bit = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_EQ, t_op0, t_op1);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_sign_bit);
+
+    /* create a new basic block which is executed if the signedness bit is
+     * different */ 
+    Instruction *icmp_inv_sig_cmp;
+    BasicBlock* sign_bb = BasicBlock::Create(C, "sign", end_bb->getParent(), end_bb);
+    if (pred == CmpInst::ICMP_SGT) {
+      /* if we check for > and the op0 positiv and op1 negative then the final
+       * result is true. if op0 negative and op1 pos, the cmp must result
+       * in false
+       */
+      icmp_inv_sig_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_op0, t_op1);
+    } else {
+      /* just the inverse of the above statement */
+      icmp_inv_sig_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_op0, t_op1);
+    }
+    sign_bb->getInstList().push_back(icmp_inv_sig_cmp);
+    BranchInst::Create(end_bb, sign_bb);
+
+    /* create a new bb which is executed if signedness is equal */
+    Instruction *icmp_usign_cmp;
+    BasicBlock* middle_bb =  BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
+    /* we can do a normal unsigned compare now */
+    icmp_usign_cmp = CmpInst::Create(Instruction::ICmp, new_pred, op0, op1);
+    middle_bb->getInstList().push_back(icmp_usign_cmp);
+    BranchInst::Create(end_bb, middle_bb);
+
+    auto term = bb->getTerminator();
+    /* if the sign is eq do a normal unsigned cmp, else we have to check the
+     * signedness bit */
+    BranchInst::Create(middle_bb, sign_bb, icmp_sign_bit, bb);
+    term->eraseFromParent();
+
+
+    PHINode *PN = PHINode::Create(Int1Ty, 2, "");
+
+    PN->addIncoming(icmp_usign_cmp, middle_bb);
+    PN->addIncoming(icmp_inv_sig_cmp, sign_bb);
+
+    BasicBlock::iterator ii(IcmpInst);
+    ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+  }
+
+  return true;
+}
+
+/* splits icmps of size bitw into two nested icmps with bitw/2 size each */
+bool SplitComparesTransform::splitCompares(Module &M, unsigned bitw) {
+  LLVMContext &C = M.getContext();
+
+  IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
+  IntegerType *OldIntType = IntegerType::get(C, bitw);
+  IntegerType *NewIntType = IntegerType::get(C, bitw / 2);
+
+  std::vector<Instruction*> icomps;
+
+  if (bitw % 2) {
+    return false;
+  }
+
+  /* not supported yet */
+  if (bitw > 64) {
+    return false;
+  }
+
+  /* get all EQ, NE, UGT, and ULT icmps of width bitw. if the other two 
+   * unctions were executed only these four predicates should exist */
+  for (auto &F : M) {
+    for (auto &BB : F) {
+      for(auto &IN: BB) {
+        CmpInst* selectcmpInst = nullptr;
+
+        if ((selectcmpInst = dyn_cast<CmpInst>(&IN))) {
+
+          if(selectcmpInst->getPredicate() != CmpInst::ICMP_EQ &&
+             selectcmpInst->getPredicate() != CmpInst::ICMP_NE &&
+             selectcmpInst->getPredicate() != CmpInst::ICMP_UGT &&
+             selectcmpInst->getPredicate() != CmpInst::ICMP_ULT
+             ) {
+            continue;
+          }
+
+          auto op0 = selectcmpInst->getOperand(0);
+          auto op1 = selectcmpInst->getOperand(1);
+
+          IntegerType* intTyOp0 = dyn_cast<IntegerType>(op0->getType());
+          IntegerType* intTyOp1 = dyn_cast<IntegerType>(op1->getType());
+
+          if (!intTyOp0 || !intTyOp1) {
+            continue;
+          }
+
+          /* check if the bitwidths are the one we are looking for */
+          if (intTyOp0->getBitWidth() != bitw || intTyOp1->getBitWidth() != bitw) {
+            continue;
+          }
+
+          icomps.push_back(selectcmpInst);
+        }
+      }
+    }
+  }
+
+  if (!icomps.size()) {
+    return false;
+  }
+
+  for (auto &IcmpInst: icomps) {
+    BasicBlock* bb = IcmpInst->getParent();
+
+    auto op0 = IcmpInst->getOperand(0);
+    auto op1 = IcmpInst->getOperand(1);
+
+    auto pred = dyn_cast<CmpInst>(IcmpInst)->getPredicate();
+
+    BasicBlock* end_bb = bb->splitBasicBlock(BasicBlock::iterator(IcmpInst));
+
+    /* create the comparison of the top halfs of the original operands */
+    Instruction *s_op0, *op0_high, *s_op1, *op1_high, *icmp_high;
+
+    s_op0 = BinaryOperator::Create(Instruction::LShr, op0, ConstantInt::get(OldIntType, bitw / 2));
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op0);
+    op0_high = new TruncInst(s_op0, NewIntType);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), op0_high);
+
+    s_op1 = BinaryOperator::Create(Instruction::LShr, op1, ConstantInt::get(OldIntType, bitw / 2));
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), s_op1);
+    op1_high = new TruncInst(s_op1, NewIntType);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), op1_high);
+
+    icmp_high = CmpInst::Create(Instruction::ICmp, pred, op0_high, op1_high);
+    bb->getInstList().insert(bb->getTerminator()->getIterator(), icmp_high);
+
+    /* now we have to destinguish between == != and > < */
+    if (pred == CmpInst::ICMP_EQ || pred == CmpInst::ICMP_NE) {
+      /* transformation for == and != icmps */
+
+      /* create a compare for the lower half of the original operands */
+      Instruction *op0_low, *op1_low, *icmp_low;
+      BasicBlock* cmp_low_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
+
+      op0_low = new TruncInst(op0, NewIntType);
+      cmp_low_bb->getInstList().push_back(op0_low);
+
+      op1_low = new TruncInst(op1, NewIntType);
+      cmp_low_bb->getInstList().push_back(op1_low);
+
+      icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low);
+      cmp_low_bb->getInstList().push_back(icmp_low);
+      BranchInst::Create(end_bb, cmp_low_bb);
+
+      /* dependant on the cmp of the high parts go to the end or go on with
+       * the comparison */
+      auto term = bb->getTerminator();
+      if (pred == CmpInst::ICMP_EQ) {
+        BranchInst::Create(cmp_low_bb, end_bb, icmp_high, bb);
+      } else {
+        /* CmpInst::ICMP_NE */
+        BranchInst::Create(end_bb, cmp_low_bb, icmp_high, bb);
+      }
+      term->eraseFromParent();
+
+      /* create the PHI and connect the edges accordingly */
+      PHINode *PN = PHINode::Create(Int1Ty, 2, "");
+      PN->addIncoming(icmp_low, cmp_low_bb);
+      if (pred == CmpInst::ICMP_EQ) {
+        PN->addIncoming(ConstantInt::get(Int1Ty, 0), bb);
+      } else {
+        /* CmpInst::ICMP_NE */
+        PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
+      }
+
+      /* replace the old icmp with the new PHI */
+      BasicBlock::iterator ii(IcmpInst);
+      ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+
+    } else {
+      /* CmpInst::ICMP_UGT and CmpInst::ICMP_ULT */
+      /* transformations for < and > */
+
+      /* create a basic block which checks for the inverse predicate. 
+       * if this is true we can go to the end if not we have to got to the
+       * bb which checks the lower half of the operands */
+      Instruction *icmp_inv_cmp, *op0_low, *op1_low, *icmp_low;
+      BasicBlock* inv_cmp_bb = BasicBlock::Create(C, "inv_cmp", end_bb->getParent(), end_bb);
+      if (pred == CmpInst::ICMP_UGT) {
+        icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, op0_high, op1_high);
+      } else {
+        icmp_inv_cmp = CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, op0_high, op1_high);
+      }
+      inv_cmp_bb->getInstList().push_back(icmp_inv_cmp);
+
+      auto term = bb->getTerminator();
+      term->eraseFromParent();
+      BranchInst::Create(end_bb, inv_cmp_bb, icmp_high, bb);
+
+      /* create a bb which handles the cmp of the lower halfs */
+      BasicBlock* cmp_low_bb = BasicBlock::Create(C, "injected", end_bb->getParent(), end_bb);
+      op0_low = new TruncInst(op0, NewIntType);
+      cmp_low_bb->getInstList().push_back(op0_low);
+      op1_low = new TruncInst(op1, NewIntType);
+      cmp_low_bb->getInstList().push_back(op1_low);
+
+      icmp_low = CmpInst::Create(Instruction::ICmp, pred, op0_low, op1_low);
+      cmp_low_bb->getInstList().push_back(icmp_low);
+      BranchInst::Create(end_bb, cmp_low_bb);
+
+      BranchInst::Create(end_bb, cmp_low_bb, icmp_inv_cmp, inv_cmp_bb);
+
+      PHINode *PN = PHINode::Create(Int1Ty, 3);
+      PN->addIncoming(icmp_low, cmp_low_bb);
+      PN->addIncoming(ConstantInt::get(Int1Ty, 1), bb);
+      PN->addIncoming(ConstantInt::get(Int1Ty, 0), inv_cmp_bb);
+
+      BasicBlock::iterator ii(IcmpInst);
+      ReplaceInstWithInst(IcmpInst->getParent()->getInstList(), ii, PN);
+    }
+  }
+  return  true;
+}
+
+bool SplitComparesTransform::runOnModule(Module &M) {
+  int bitw = 64;
+
+  char* bitw_env = getenv("LAF_SPLIT_COMPARES_BITW");
+  if (bitw_env) {
+    bitw = atoi(bitw_env);
+  }
+
+  simplifyCompares(M);
+
+  simplifySignedness(M);
+
+  errs() << "Split-compare-pass by laf.intel@gmail.com\n"; 
+
+  switch (bitw) {
+    case 64:
+      errs() << "Running split-compare-pass " << 64 << "\n"; 
+      splitCompares(M, 64);
+
+      [[clang::fallthrough]];
+      /* fallthrough */
+    case 32:
+      errs() << "Running split-compare-pass " << 32 << "\n"; 
+      splitCompares(M, 32);
+
+      [[clang::fallthrough]];
+      /* fallthrough */
+    case 16:
+      errs() << "Running split-compare-pass " << 16 << "\n"; 
+      splitCompares(M, 16);
+      break;
+
+    default:
+      errs() << "NOT Running split-compare-pass \n"; 
+      return false;
+      break;
+  }
+
+  verifyModule(M);
+  return true;
+}
+
+static void registerSplitComparesPass(const PassManagerBuilder &,
+                         legacy::PassManagerBase &PM) {
+  PM.add(new SplitComparesTransform());
+}
+
+static RegisterStandardPasses RegisterSplitComparesPass(
+    PassManagerBuilder::EP_OptimizerLast, registerSplitComparesPass);
+
+static RegisterStandardPasses RegisterSplitComparesTransPass0(
+    PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitComparesPass);
diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc
new file mode 100644
index 00000000..1341c7f9
--- /dev/null
+++ b/llvm_mode/split-switches-pass.so.cc
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2016 laf-intel
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/IPO/PassManagerBuilder.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/Analysis/ValueTracking.h"
+
+#include <set>
+
+using namespace llvm;
+
+namespace {
+
+  class SplitSwitchesTransform : public ModulePass {
+
+    public:
+      static char ID;
+      SplitSwitchesTransform() : ModulePass(ID) {
+      } 
+
+      bool runOnModule(Module &M) override;
+
+#if __clang_major__ >= 4
+      StringRef getPassName() const override {
+#else
+      const char * getPassName() const override {
+#endif
+        return "splits switch constructs";
+      }
+      struct CaseExpr {
+        ConstantInt* Val;
+        BasicBlock* BB;
+
+        CaseExpr(ConstantInt *val = nullptr, BasicBlock *bb = nullptr) :
+          Val(val), BB(bb) { }
+      };
+
+    typedef std::vector<CaseExpr> CaseVector;
+
+    private:
+      bool splitSwitches(Module &M);
+      bool transformCmps(Module &M, const bool processStrcmp, const bool processMemcmp);
+      BasicBlock* switchConvert(CaseVector Cases, std::vector<bool> bytesChecked,
+                                BasicBlock* OrigBlock, BasicBlock* NewDefault,
+                                Value* Val, unsigned level);
+  };
+
+}
+
+char SplitSwitchesTransform::ID = 0;
+
+
+/* switchConvert - Transform simple list of Cases into list of CaseRange's */
+BasicBlock* SplitSwitchesTransform::switchConvert(CaseVector Cases, std::vector<bool> bytesChecked, 
+                                            BasicBlock* OrigBlock, BasicBlock* NewDefault,
+                                            Value* Val, unsigned level) {
+
+  unsigned ValTypeBitWidth = Cases[0].Val->getBitWidth();
+  IntegerType *ValType  = IntegerType::get(OrigBlock->getContext(), ValTypeBitWidth);
+  IntegerType *ByteType = IntegerType::get(OrigBlock->getContext(), 8);
+  unsigned BytesInValue = bytesChecked.size();
+  std::vector<uint8_t> setSizes;
+  std::vector<std::set<uint8_t>> byteSets(BytesInValue, std::set<uint8_t>());
+
+
+  /* for each of the possible cases we iterate over all bytes of the values
+   * build a set of possible values at each byte position in byteSets */
+  for (CaseExpr& Case: Cases) {
+    for (unsigned i = 0; i < BytesInValue; i++) {
+
+      uint8_t byte = (Case.Val->getZExtValue() >> (i*8)) & 0xFF;
+      byteSets[i].insert(byte);
+    }
+  }
+
+  unsigned smallestIndex = 0;
+  unsigned smallestSize = 257;
+  for(unsigned i = 0; i < byteSets.size(); i++) {
+    if (bytesChecked[i])
+      continue;
+    if (byteSets[i].size() < smallestSize) {
+      smallestIndex = i;
+      smallestSize = byteSets[i].size();
+    }
+  }
+  assert(bytesChecked[smallestIndex] == false);
+
+  /* there are only smallestSize different bytes at index smallestIndex */
+ 
+  Instruction *Shift, *Trunc;
+  Function* F = OrigBlock->getParent();
+  BasicBlock* NewNode = BasicBlock::Create(Val->getContext(), "NodeBlock", F);
+  Shift = BinaryOperator::Create(Instruction::LShr, Val, ConstantInt::get(ValType, smallestIndex * 8));
+  NewNode->getInstList().push_back(Shift);
+
+  if (ValTypeBitWidth > 8) {
+    Trunc = new TruncInst(Shift, ByteType);
+    NewNode->getInstList().push_back(Trunc);
+  }
+  else {
+    /* not necessary to trunc */
+    Trunc = Shift;
+  }
+
+  /* this is a trivial case, we can directly check for the byte,
+   * if the byte is not found go to default. if the byte was found
+   * mark the byte as checked. if this was the last byte to check
+   * we can finally execute the block belonging to this case */
+
+
+  if (smallestSize == 1) {
+    uint8_t byte = *(byteSets[smallestIndex].begin());
+
+    /* insert instructions to check whether the value we are switching on is equal to byte */
+    ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_EQ, Trunc, ConstantInt::get(ByteType, byte), "byteMatch");
+    NewNode->getInstList().push_back(Comp);
+
+    bytesChecked[smallestIndex] = true;
+    if (std::all_of(bytesChecked.begin(), bytesChecked.end(), [](bool b){return b;} )) {
+      assert(Cases.size() == 1);
+      BranchInst::Create(Cases[0].BB, NewDefault, Comp, NewNode);
+
+      /* we have to update the phi nodes! */
+      for (BasicBlock::iterator I = Cases[0].BB->begin(); I != Cases[0].BB->end(); ++I) {
+        if (!isa<PHINode>(&*I)) {
+          continue;
+        }
+        PHINode *PN = cast<PHINode>(I);
+
+        /* Only update the first occurence. */
+        unsigned Idx = 0, E = PN->getNumIncomingValues();
+        for (; Idx != E; ++Idx) {
+          if (PN->getIncomingBlock(Idx) == OrigBlock) {
+            PN->setIncomingBlock(Idx, NewNode);
+            break;
+          }
+        }
+      }
+    }
+    else {
+      BasicBlock* BB = switchConvert(Cases, bytesChecked, OrigBlock, NewDefault, Val, level + 1);
+      BranchInst::Create(BB, NewDefault, Comp, NewNode);
+    }
+  }
+  /* there is no byte which we can directly check on, split the tree */
+  else {
+
+    std::vector<uint8_t> byteVector;
+    std::copy(byteSets[smallestIndex].begin(), byteSets[smallestIndex].end(), std::back_inserter(byteVector));
+    std::sort(byteVector.begin(), byteVector.end());
+    uint8_t pivot = byteVector[byteVector.size() / 2];
+
+    /* we already chose to divide the cases based on the value of byte at index smallestIndex
+     * the pivot value determines the threshold for the decicion; if a case value
+     * is smaller at this byte index move it to the LHS vector, otherwise to the RHS vector */
+
+    CaseVector LHSCases, RHSCases;
+
+    for (CaseExpr& Case: Cases) {
+      uint8_t byte = (Case.Val->getZExtValue() >> (smallestIndex*8)) & 0xFF;
+
+      if (byte < pivot) {
+        LHSCases.push_back(Case);
+      }
+      else {
+        RHSCases.push_back(Case);
+      }
+    }
+    BasicBlock *LBB, *RBB;
+    LBB = switchConvert(LHSCases, bytesChecked, OrigBlock, NewDefault, Val, level + 1);
+    RBB = switchConvert(RHSCases, bytesChecked, OrigBlock, NewDefault, Val, level + 1);
+
+    /* insert instructions to check whether the value we are switching on is equal to byte */
+    ICmpInst* Comp = new ICmpInst(ICmpInst::ICMP_ULT, Trunc, ConstantInt::get(ByteType, pivot), "byteMatch");
+    NewNode->getInstList().push_back(Comp);
+    BranchInst::Create(LBB, RBB, Comp, NewNode);
+
+  }
+
+  return NewNode;
+}
+
+bool SplitSwitchesTransform::splitSwitches(Module &M) {
+
+  std::vector<SwitchInst*> switches;
+
+  /* iterate over all functions, bbs and instruction and add
+   * all switches to switches vector for later processing */
+  for (auto &F : M) {
+    for (auto &BB : F) {
+      SwitchInst* switchInst = nullptr;
+
+      if ((switchInst = dyn_cast<SwitchInst>(BB.getTerminator()))) {
+        if (switchInst->getNumCases() < 1)
+            continue;
+          switches.push_back(switchInst);
+      }
+    }
+  }
+
+  if (!switches.size())
+    return false;
+  errs() << "Rewriting " << switches.size() << " switch statements " << "\n";
+
+  for (auto &SI: switches) {
+
+    BasicBlock *CurBlock = SI->getParent();
+    BasicBlock *OrigBlock = CurBlock;
+    Function *F = CurBlock->getParent();
+    /* this is the value we are switching on */
+    Value *Val = SI->getCondition();
+    BasicBlock* Default = SI->getDefaultDest();
+
+    /* If there is only the default destination, don't bother with the code below. */
+    if (!SI->getNumCases()) {
+      continue;
+    }
+
+    /* Create a new, empty default block so that the new hierarchy of
+     * if-then statements go to this and the PHI nodes are happy.
+     * if the default block is set as an unreachable we avoid creating one
+     * because will never be a valid target.*/
+    BasicBlock *NewDefault = nullptr;
+    NewDefault = BasicBlock::Create(SI->getContext(), "NewDefault");
+    NewDefault->insertInto(F, Default);
+    BranchInst::Create(Default, NewDefault);
+
+
+    /* Prepare cases vector. */
+    CaseVector Cases;
+    for (SwitchInst::CaseIt i = SI->case_begin(), e = SI->case_end(); i != e; ++i)
+#if __clang_major__ < 7
+      Cases.push_back(CaseExpr(i.getCaseValue(), i.getCaseSuccessor()));
+#else
+      Cases.push_back(CaseExpr(i->getCaseValue(), i->getCaseSuccessor()));
+#endif
+    std::vector<bool> bytesChecked(Cases[0].Val->getBitWidth() / 8, false);
+    BasicBlock* SwitchBlock = switchConvert(Cases, bytesChecked, OrigBlock, NewDefault, Val, 0);
+
+    /* Branch to our shiny new if-then stuff... */
+    BranchInst::Create(SwitchBlock, OrigBlock);
+
+    /* We are now done with the switch instruction, delete it. */
+    CurBlock->getInstList().erase(SI);
+
+
+   /* we have to update the phi nodes! */
+   for (BasicBlock::iterator I = Default->begin(); I != Default->end(); ++I) {
+     if (!isa<PHINode>(&*I)) {
+      continue;
+     }
+     PHINode *PN = cast<PHINode>(I);
+
+     /* Only update the first occurence. */
+     unsigned Idx = 0, E = PN->getNumIncomingValues();
+     for (; Idx != E; ++Idx) {
+       if (PN->getIncomingBlock(Idx) == OrigBlock) {
+         PN->setIncomingBlock(Idx, NewDefault);
+         break;
+       }
+     }
+   }
+ }
+
+ verifyModule(M);
+ return true;
+}
+
+bool SplitSwitchesTransform::runOnModule(Module &M) {
+
+  llvm::errs() << "Running split-switches-pass by laf.intel@gmail.com\n"; 
+  splitSwitches(M);
+  verifyModule(M);
+
+  return true;
+}
+
+static void registerSplitSwitchesTransPass(const PassManagerBuilder &,
+                            legacy::PassManagerBase &PM) {
+
+  auto p = new SplitSwitchesTransform();
+  PM.add(p);
+
+}
+
+static RegisterStandardPasses RegisterSplitSwitchesTransPass(
+    PassManagerBuilder::EP_OptimizerLast, registerSplitSwitchesTransPass);
+
+static RegisterStandardPasses RegisterSplitSwitchesTransPass0(
+    PassManagerBuilder::EP_EnabledOnOptLevel0, registerSplitSwitchesTransPass);