From 64bb573a953a854045bd9b7076901fddadc0edbf Mon Sep 17 00:00:00 2001 From: Tomas Meszaros Date: Wed, 5 Dec 2018 10:53:03 +0100 Subject: [PATCH] apex launcher done --- Makefile | 10 +- apex.py | 74 ++++++++++--- examples/mod1/example_mod1.c | 2 +- src/apex/apex.cpp | 1 + src/apex/apex.h | 20 +--- src/apex/apexlib.c | 9 +- src/c-code/example.c | 17 --- src/c-code/example_mod1.c | 21 ---- src/c-code/example_mod2.c | 23 ---- src/c-code/test.c | 32 ------ src/c-code/test_dependencies_minimal.c | 42 ------- src/run | 147 ------------------------- src/run.sh | 144 ------------------------ 13 files changed, 80 insertions(+), 462 deletions(-) delete mode 100644 src/c-code/example.c delete mode 100644 src/c-code/example_mod1.c delete mode 100644 src/c-code/example_mod2.c delete mode 100644 src/c-code/test.c delete mode 100644 src/c-code/test_dependencies_minimal.c delete mode 100644 src/run delete mode 100755 src/run.sh diff --git a/Makefile b/Makefile index fbaf2f4..7c80955 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,12 @@ -build: +# Created by Tomas Meszaros (exo at tty dot com, tmeszaro at redhat dot com) +# +# Published under Apache 2.0 license. +# See LICENSE for details. + +# Makefile for building APEXPass and generating documentation +# run: $ make build, to build APEXPass + +build: clean cd src; \ ./build.sh; diff --git a/apex.py b/apex.py index ea97ba8..f2ca7a4 100644 --- a/apex.py +++ b/apex.py @@ -1,43 +1,85 @@ #!/usr/bin/env python3 +# Created by Tomas Meszaros (exo at tty dot com, tmeszaro at redhat dot com) +# +# Published under Apache 2.0 license. +# See LICENSE for details. + +""" +python3 apex.py examples/mod1/example_mod1.bc example_mod1.c 11 --export=true +""" + import argparse import shlex import subprocess import sys -def execute(cmd, print_output=True): +def execute(cmd, print_output=False): try: out = subprocess.check_output(cmd, shell=True) - print(out.decode("utf-8")) + if print_output: + print(out.decode("utf-8")) except subprocess.CalledProcessError as e: sys.stderr.write(str(e) + '\n') return None +# Config cmd line args. parser = argparse.ArgumentParser() +parser.add_argument("code", type=str, help="C source code compiled into LLVM bytecode.") +parser.add_argument("file", type=str, help="Target file name (NOT FULL PATH).") +parser.add_argument("line", type=int, help="Target line number.") +parser.add_argument("--export", type=str, help="true/false for exporting call graphs.") -parser.add_argument('--code', type=str, help='input C source code compiled into LLVM bytecode') -parser.add_argument('--file', type=str, help='file where is the target (NOT FULL PATH)') -parser.add_argument('--line', type=int, help='target line number in file') - - +# Parse cmd line args. args = parser.parse_args() code = args.code target_file = args.file line = args.line +export = args.export -print("code", code) -print("target_file", target_file) -print("line", line) +execute("rm -rf build; mkdir build") +# Compile apexlib to the bytecode. +execute("clang -O0 -g -c -emit-llvm src/apex/apexlib.c -o build/apexlib.bc") -execute("rm -rf build; mkdir build") -execute("clang -O0 -g -c -emit-llvm src/apex/apexlib.c -o build/bytecode_from_apexlib.bc") -execute("llvm-link build/bytecode_from_apexlib.bc {INPUT} -S -o=build/linked_ir.ll".format(INPUT=code)) -execute("llvm-as build/linked_ir.ll -o build/bytecode_from_linked_input.bc") +# Link @code with apexlib bytecode. +execute("llvm-link build/apexlib.bc {INPUT} -S -o=build/linked.ll".format(INPUT=code)) +# Procedure bytecode from linked input and apexlib. +execute("llvm-as build/linked.ll -o build/linked.bc") -opt = """opt -o build/bytecode_from_apex.bc -load src/build/apex/libAPEXPass.so -apex -file={FILE} -line={LINE} < build/bytecode_from_linked_input.bc 2> build/apex.out +# Run APEXPass on the linked bytecode we produced above. +# Save log to the build/apex.log. +opt = """opt -o build/apex.bc -load src/build/apex/libAPEXPass.so -apex -file={FILE} -line={LINE} < build/linked.bc 2> build/apex.log """.format(FILE=target_file, LINE=line) -print(opt) execute(opt) +# Disassembly apexlib and final extracted bytecode for dbg & logging purposes. +execute("llvm-dis build/apexlib.bc -o build/apexlib.ll") +execute("llvm-dis build/apex.bc -o build/apex.ll") + +# Run final extracted bytecode and save the result to the build/apex.out. +execute("lli build/apex.bc > build/apex.out") +execute("cat build/apex.out", print_output=True) + + +# Optional call graphs export +if export and export == "true": + execute("rm -rf build/callgraphs; mkdir build/callgraphs") + execute("opt -dot-callgraph {INPUT} > /dev/null".format(INPUT=code)) + execute("mv callgraph.dot callgraph_no_opt.dot") + execute("dot callgraph_no_opt.dot -Tsvg -O") + execute("rm -rf callgraph_no_opt.dot") + execute("mv callgraph_no_opt.dot.svg build/callgraphs") + + execute("opt -dot-callgraph build/linked.bc > /dev/null") + execute("mv callgraph.dot callgraph_linked.dot") + execute("dot callgraph_linked.dot -Tsvg -O") + execute("rm -rf callgraph_linked.dot") + execute("mv callgraph_linked.dot.svg build/callgraphs") + + execute("opt -dot-callgraph build/apex.bc > /dev/null") + execute("mv callgraph.dot callgraph_apex.dot") + execute("dot callgraph_apex.dot -Tsvg -O") + execute("rm -rf callgraph_apex.dot") + execute("mv callgraph_apex.dot.svg build/callgraphs") diff --git a/examples/mod1/example_mod1.c b/examples/mod1/example_mod1.c index 87aa4f6..df77622 100644 --- a/examples/mod1/example_mod1.c +++ b/examples/mod1/example_mod1.c @@ -4,7 +4,7 @@ int foo(int n) { } int qux(void) { - return 42; + return 42; } int bar(void) { diff --git a/src/apex/apex.cpp b/src/apex/apex.cpp index 462ba86..3cc4464 100644 --- a/src/apex/apex.cpp +++ b/src/apex/apex.cpp @@ -11,6 +11,7 @@ // - target only non global int // TODO: user I.getprevnode() or I.getnextnode() to for injecting +// TODO: remove unused includes #include "apex.h" diff --git a/src/apex/apex.h b/src/apex/apex.h index bf1cd48..2ab7aee 100644 --- a/src/apex/apex.h +++ b/src/apex/apex.h @@ -8,10 +8,10 @@ #pragma once -#include -#include -#include -#include +//#include +//#include +//#include +//#include #include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" @@ -56,19 +56,9 @@ std::vector PROTECTED_FCNS = { // These belong to the _apex_extract_int function. "_apex_extract_int", - "abs", - "log10", - "floor", - "fopen", - "fputs", - "fclose", - "exit", - "sprintf", - - // Keep printf calls. "printf", - // Introduced with debug symbols. + // LLVM stuff "llvm.dbg.declare", "llvm.stackrestore", "llvm.stacksave", diff --git a/src/apex/apexlib.c b/src/apex/apexlib.c index 0d36a48..ed49f74 100644 --- a/src/apex/apexlib.c +++ b/src/apex/apexlib.c @@ -2,14 +2,16 @@ #include #include -#define APEX_OUTPUT "apex.out" - /// Function used for getting out of the program, usually after calling @_apex_extract_int(). void _apex_exit(int exit_code) { exit(exit_code); } -/// Function used for dumping value @i to file @APEX_OUTPUT. +/// Function used for extracting value %i. +void _apex_extract_int(int i) { + printf("%d", i); +} +/* void _apex_extract_int(int i) { // Figure out number of digits @i has, // so we can allocate big enough buffer. @@ -36,3 +38,4 @@ void _apex_extract_int(int i) { printf("Error: Could not save to file!\n"); } } +*/ diff --git a/src/c-code/example.c b/src/c-code/example.c deleted file mode 100644 index 30b11e2..0000000 --- a/src/c-code/example.c +++ /dev/null @@ -1,17 +0,0 @@ -int foo(int n) { - int x = n + 10; - return x; -} - -int bar(void) { - int y = 42; - return y; -} - -int main(void) { - int some_int = 10; - int foo_result = foo(some_int); - int bar_result = bar(); - - return 0; -} diff --git a/src/c-code/example_mod1.c b/src/c-code/example_mod1.c deleted file mode 100644 index 87aa4f6..0000000 --- a/src/c-code/example_mod1.c +++ /dev/null @@ -1,21 +0,0 @@ -int foo(int n) { - int x = n + 10; - return x; -} - -int qux(void) { - return 42; -} - -int bar(void) { - int y = qux(); - return y; -} - -int main(void) { - int some_int = 10; - int foo_result = foo(some_int); - int bar_result = bar(); - - return 0; -} diff --git a/src/c-code/example_mod2.c b/src/c-code/example_mod2.c deleted file mode 100644 index e1d6262..0000000 --- a/src/c-code/example_mod2.c +++ /dev/null @@ -1,23 +0,0 @@ -int foo(int n) { - int x = n + 10; - return x; -} - -int qux(void) { - return 42; -} - -int bar(void) { - int y = qux(); - return y; -} - -int main(void) { - int some_int = 10; - int foo_result = foo(some_int); - int n = 10; - if (n < 42) { - int bar_result = bar(); - } - return 0; -} diff --git a/src/c-code/test.c b/src/c-code/test.c deleted file mode 100644 index 0d8d914..0000000 --- a/src/c-code/test.c +++ /dev/null @@ -1,32 +0,0 @@ -#include - -int x(void); -int y(void); -int a(void); -int b(void); - -int x(void) { - printf("x\n"); - y(); -} - -int y(void) { - printf("y\n"); -} - -int a(void) { - printf("a\n"); - y(); - b(); -} - -int b(void) { - printf("b\n"); -} - -int main() { - x(); - a(); - - return 0; -} diff --git a/src/c-code/test_dependencies_minimal.c b/src/c-code/test_dependencies_minimal.c deleted file mode 100644 index 3e12751..0000000 --- a/src/c-code/test_dependencies_minimal.c +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include - - -int n(void) { - printf("n: in\n"); - return 10; -} - -int z(void) { - printf("z: in\n"); - int a = 1; - int b = n(); - return 10; -} - -int x(void) { - printf("x: in\n"); - int test = 1; - return z(); -} - -int flag(void) { - printf("flag: in\n"); - return 0; -} - -int main(int argc, char **argv) { - int f = flag(); - int test = x(); - - if (f == 0) { - printf("if: in\n"); - int x_ret = x(); - } else { - printf("else: in\n"); - int n_ret = n(); - } - - int z_ret = z(); - return 0; -} diff --git a/src/run b/src/run deleted file mode 100644 index 42141dd..0000000 --- a/src/run +++ /dev/null @@ -1,147 +0,0 @@ -#!/bin/bash - -# Created by Tomas Meszaros (exo at tty dot com, tmeszaro at redhat dot com) -# -# Published under Apache 2.0 license. -# See LICENSE for details. - -# What is this: -# Script for building APEX as LLVM pass and then generating bytecode from -# input before and after running APEX (+running code formatting, -# generating images, etc.) - -# ============================================================================= -# User Input ================================================================== -FILE="c-code/example_mod2.c" -LINE=11 - -# user needs to compile the input with debug symbols and emit llvm -INPUT_SOURCE="c-code/example_mod2.c" -clang -O0 -g -c -emit-llvm ${INPUT_SOURCE} -o build/${BYTECODE_FROM_INPUT} - -BYTECODE_FROM_INPUT="bytecode_from_input.bc" # No optimizations. - -# ============================================================================= -# Constants =================================================================== - -APEX_LOG="apex.log" -APEX_OUT="apex.out" -INPUT_LIB="apex/apexlib.c" - -# Generated bytecodes during all stages of processing. -BYTECODE_FROM_APEXLIB="bytecode_from_apexlib.bc" # Compiled libraries from ${INPUT_LIB} -BYTECODE_FROM_LINKED_INPUT_LIB="bytecode_from_linked.bc" # Linked input and lib bytecode. APEXPass will work with this. -LINKED_DISASSEMBLY="bytecode_from_linked.ll" -BYTECODE_FROM_APEX="bytecode_from_apex.bc" # APEXPass bytecode. - -# ============================================================================= -# Running code formatter ====================================================== - -echo "========= Running clang-format." - -clang-format -style=llvm -i apex/*.cpp apex/*.h - -# ============================================================================= -# Compile to bytecode and run basic opts and than our opt ===================== - -echo "========= Compiling apexlib." - -# compile apex lib -clang -O0 -lm -g -c -emit-llvm ${INPUT_LIB} -o build/${BYTECODE_FROM_APEXLIB} - - -echo "========= Linking input with apex lib." -# We are linking input after basic opts. -llvm-link build/${BYTECODE_FROM_APEXLIB} build/${BYTECODE_FROM_INPUT} -S -o=build/${LINKED_DISASSEMBLY} -# Produce readable IR for logging purposes. -llvm-as build/${LINKED_DISASSEMBLY} -o build/${BYTECODE_FROM_LINKED_INPUT_LIB} - -echo "========= Running APEXPass." - -# run APEXPass without additional opts -opt -o build/${BYTECODE_FROM_APEX} \ - -load build/apex/libAPEXPass.so \ - -apex -file=${FILE} -line=${LINE} \ - < build/${BYTECODE_FROM_LINKED_INPUT_LIB} 2> ${APEX_LOG} - -## run APEXPass with ${BASIC_OPTS} -#opt -o build/${BYTECODE_FROM_APEX} \ -# -load build/apex/libAPEXPass.so \ -# -apex ${BASIC_OPTS} -file=${FILE} -line=${LINE} \ -# < build/${BYTECODE_FROM_LINKED_INPUT_LIB} 2> ${APEX_LOG} - - -# ============================================================================== -# Generate callgraphs before and after ========================================= - -echo "========= Exporting callgraphs." - -# Run callgraph exporter. -cd build -rm -rf callgraphs -mkdir callgraphs -cd callgraphs - -opt -dot-callgraph ../${BYTECODE_FROM_INPUT} > /dev/null -mv callgraph.dot callgraph_no_opt.dot -dot callgraph_no_opt.dot -Tsvg -O - -opt -dot-callgraph ../${BYTECODE_FROM_APEX} > /dev/null -mv callgraph.dot callgraph_apex_opt.dot -dot callgraph_apex_opt.dot -Tsvg -O - -cd ../.. - - -# ============================================================================== -# DG tools output ============================================================== - -echo "========= Running dg tools." - -cd build -rm -rf dg_tools -mkdir dg_tools -cd dg_tools - - -../../dg/build/tools/llvm-dg-dump ../${BYTECODE_FROM_INPUT} > llvm_dg_dump_no_opt.dot -dot llvm_dg_dump_no_opt.dot -Tpdf -O - -../../dg/build/tools/llvm-dg-dump -no-control ../${BYTECODE_FROM_INPUT} > llvm_dg_dump_no_control_no_opt.dot -dot llvm_dg_dump_no_control_no_opt.dot -Tpdf -O - -../../dg/build/tools/llvm-dg-dump -no-data ../${BYTECODE_FROM_INPUT} > llvm_dg_dump_no_data_no_opt.dot -dot llvm_dg_dump_no_data_no_opt.dot -Tpdf -O - -../../dg/build/tools/llvm-dg-dump -bb-only ../${BYTECODE_FROM_INPUT} > llvm_dg_dump_bb_only_no_opt.dot -dot llvm_dg_dump_bb_only_no_opt.dot -Tpdf -O - -../../dg/build/tools/llvm-ps-dump -dot ../${BYTECODE_FROM_INPUT} > llvm_ps_dump_no_opt.dot -dot llvm_ps_dump_no_opt.dot -Tsvgz -O - -../../dg/build/tools/llvm-rd-dump -dot ../${BYTECODE_FROM_INPUT} > llvm_rd_dump_no_opt.dot -dot llvm_rd_dump_no_opt.dot -Tpdf -O - -cd ../.. - - -# ============================================================================== -# Disassemble bytecode so We can look inside =================================== - -echo "========= Disassembling llvm bytecode." - -llvm-dis build/${BYTECODE_FROM_INPUT} -llvm-dis build/${BYTECODE_FROM_APEX} -llvm-dis build/${BYTECODE_FROM_APEXLIB} - - -# ============================================================================== -# Run generated bytecodes ====================================================== - -# run bytecode after basic opts -echo "========= Running ${BYTECODE_FROM_INPUT}" -lli build/${BYTECODE_FROM_INPUT} - -# run apexpass and execute modified bytecode -echo "========= Running ${BYTECODE_FROM_APEX}" -lli build/${BYTECODE_FROM_APEX} > ${APEX_OUT} diff --git a/src/run.sh b/src/run.sh deleted file mode 100755 index 0b76f2f..0000000 --- a/src/run.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/bin/bash - -# Created by Tomas Meszaros (exo at tty dot com, tmeszaro at redhat dot com) -# -# Published under Apache 2.0 license. -# See LICENSE for details. - -# What is this: -# Script for building APEX as LLVM pass and then generating bytecode from -# input before and after running APEX (+running code formatting, -# generating images, etc.) - -# ============================================================================= -# User Input ================================================================== -#FILE="c-code/example_mod2.c" -#LINE=11 -# user needs to compile the input with debug symbols and emit llvm -#BYTECODE_FROM_INPUT="bytecode_from_input.bc" # No optimizations. -#INPUT_SOURCE="c-code/example_mod2.c" -#clang -O0 -g -c -emit-llvm ${INPUT_SOURCE} -o build/${BYTECODE_FROM_INPUT} - -echo "========= In run.sh." - -BYTECODE_FROM_INPUT=$1 -FILE=$2 -LINE=$3 - -echo $1 -echo $2 -echo $3 - - - -# ============================================================================= -# Constants =================================================================== - -APEX_LOG="apex.log" -APEX_OUT="apex.out" -INPUT_LIB="apex/apexlib.c" - -# Generated bytecodes during all stages of processing. -BYTECODE_FROM_APEXLIB="bytecode_from_apexlib.bc" # Compiled libraries from ${INPUT_LIB} -BYTECODE_FROM_LINKED_INPUT_LIB="bytecode_from_linked.bc" # Linked input and lib bytecode. APEXPass will work with this. -LINKED_DISASSEMBLY="bytecode_from_linked.ll" -BYTECODE_FROM_APEX="bytecode_from_apex.bc" # APEXPass bytecode. - -# ============================================================================= -# Running code formatter ====================================================== - -echo "========= Running clang-format." - -clang-format -style=llvm -i apex/*.cpp apex/*.h - -# ============================================================================= -# Compile to bytecode and run basic opts and than our opt ===================== - -echo "========= Compiling apexlib." - -# compile apex lib -clang -O0 -g -c -emit-llvm ${INPUT_LIB} -o build/${BYTECODE_FROM_APEXLIB} - - -echo "========= Linking input with apex lib." -# We are linking input after basic opts. -llvm-link build/${BYTECODE_FROM_APEXLIB} ../${BYTECODE_FROM_INPUT} -S -o=build/${LINKED_DISASSEMBLY} -llvm-as build/${LINKED_DISASSEMBLY} -o build/${BYTECODE_FROM_LINKED_INPUT_LIB} - -echo "========= Running APEXPass." - -# run APEXPass without additional opts -opt -o build/${BYTECODE_FROM_APEX} \ - -load build/apex/libAPEXPass.so \ - -apex -file=${FILE} -line=${LINE} \ - < build/${BYTECODE_FROM_LINKED_INPUT_LIB} 2> ${APEX_LOG} - -## run APEXPass with ${BASIC_OPTS} -#opt -o build/${BYTECODE_FROM_APEX} \ -# -load build/apex/libAPEXPass.so \ -# -apex ${BASIC_OPTS} -file=${FILE} -line=${LINE} \ -# < build/${BYTECODE_FROM_LINKED_INPUT_LIB} 2> ${APEX_LOG} - - -# ============================================================================== -# Generate callgraphs before and after ========================================= - -#echo "========= Exporting callgraphs." -# -## Run callgraph exporter. -#cd build -#rm -rf callgraphs -#mkdir callgraphs -#cd callgraphs -# -#opt -dot-callgraph ${BYTECODE_FROM_INPUT} > /dev/null -#mv callgraph.dot callgraph_no_opt.dot -#dot callgraph_no_opt.dot -Tsvg -O -# -#opt -dot-callgraph ${BYTECODE_FROM_APEX} > /dev/null -#mv callgraph.dot callgraph_apex_opt.dot -#dot callgraph_apex_opt.dot -Tsvg -O -# -#cd ../.. - - -# ============================================================================== -# DG tools output ============================================================== - -#echo "========= Running dg tools." -# -#cd build -#rm -rf dg_tools -#mkdir dg_tools -#cd dg_tools -# -# -#../../dg/build/tools/llvm-dg-dump ${BYTECODE_FROM_INPUT} > llvm_dg_dump_no_opt.dot -#dot llvm_dg_dump_no_opt.dot -Tpdf -O -# -#../../dg/build/tools/llvm-dg-dump -no-control ${BYTECODE_FROM_INPUT} > llvm_dg_dump_no_control_no_opt.dot -#dot llvm_dg_dump_no_control_no_opt.dot -Tpdf -O -# -#../../dg/build/tools/llvm-dg-dump -no-data ${BYTECODE_FROM_INPUT} > llvm_dg_dump_no_data_no_opt.dot -#dot llvm_dg_dump_no_data_no_opt.dot -Tpdf -O -# -#../../dg/build/tools/llvm-dg-dump -bb-only ${BYTECODE_FROM_INPUT} > llvm_dg_dump_bb_only_no_opt.dot -#dot llvm_dg_dump_bb_only_no_opt.dot -Tpdf -O -# -#../../dg/build/tools/llvm-ps-dump -dot ${BYTECODE_FROM_INPUT} > llvm_ps_dump_no_opt.dot -#dot llvm_ps_dump_no_opt.dot -Tsvgz -O -# -#../../dg/build/tools/llvm-rd-dump -dot ${BYTECODE_FROM_INPUT} > llvm_rd_dump_no_opt.dot -#dot llvm_rd_dump_no_opt.dot -Tpdf -O -# -#cd ../.. - - -# ============================================================================== -# Disassemble bytecode so We can look inside =================================== - -echo "========= Disassembling llvm bytecode." - -#llvm-dis ${BYTECODE_FROM_INPUT} -#llvm-dis build/${BYTECODE_FROM_APEX} -#llvm-dis build/${BYTECODE_FROM_APEXLIB}