From dd85959391a9cd043c9965949aa19bcf4532feb9 Mon Sep 17 00:00:00 2001 From: Koustubha Bhat Date: Fri, 6 Jun 2014 16:20:39 +0200 Subject: [PATCH] LLVM Hello pass: inserts printf statement in main() method. --- minix/llvm/generate_gold_plugin.sh | 2 + .../passes/WeakAliasModuleOverride/Makefile | 2 +- minix/llvm/passes/hello/Makefile | 26 ++ minix/llvm/passes/hello/hello.cpp | 114 +++++++++ minix/llvm/passes/hello/pass.h | 35 +++ minix/llvm/passes/hello/pass_hello.h | 224 ++++++++++++++++++ share/mk/bsd.own.mk | 3 +- 7 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 minix/llvm/passes/hello/Makefile create mode 100644 minix/llvm/passes/hello/hello.cpp create mode 100644 minix/llvm/passes/hello/pass.h create mode 100644 minix/llvm/passes/hello/pass_hello.h diff --git a/minix/llvm/generate_gold_plugin.sh b/minix/llvm/generate_gold_plugin.sh index 9b8f42875..ea88b3cb4 100755 --- a/minix/llvm/generate_gold_plugin.sh +++ b/minix/llvm/generate_gold_plugin.sh @@ -63,3 +63,5 @@ cp ${OBJ_LLVM}/./Release+Asserts/bin/llvm-* ${CROSS_TOOLS} cd ${NETBSDSRCDIR}/minix/llvm/passes/WeakAliasModuleOverride make LLVMPREFIX=${OBJ_LLVM}/./Release+Asserts/ install +cd ${NETBSDSRCDIR}/minix/llvm/passes/hello +make LLVMPREFIX=${OBJ_LLVM}/./Release+Asserts/ install diff --git a/minix/llvm/passes/WeakAliasModuleOverride/Makefile b/minix/llvm/passes/WeakAliasModuleOverride/Makefile index 38333d677..cb708a802 100644 --- a/minix/llvm/passes/WeakAliasModuleOverride/Makefile +++ b/minix/llvm/passes/WeakAliasModuleOverride/Makefile @@ -2,7 +2,7 @@ QUIET=@ ECHO=echo CP=cp -PASSLIBNAME:= weak-alias-module-override +PASSLIBNAME:= weak-alias-module-override.so LLVM_VERSION = $($LLVMPREFIX/bin/llvm-config --version | sed "s/[^0-9]//g") CFLAGS += -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -DHAVE_EXCEPTIONS=0 diff --git a/minix/llvm/passes/hello/Makefile b/minix/llvm/passes/hello/Makefile new file mode 100644 index 000000000..744dc90f8 --- /dev/null +++ b/minix/llvm/passes/hello/Makefile @@ -0,0 +1,26 @@ +QUIET=@ +ECHO=echo +CP=cp + +PASSLIBNAME:= hello.so + +LLVM_VERSION=$(shell ($(LLVMPREFIX)/bin/llvm-config --version | sed "s/[^0-9]//g")) +CFLAGS += -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -DHAVE_EXCEPTIONS=0 +CFLAGS += $(shell $(LLVMPREFIX)/bin/llvm-config --cxxflags) -g -DLLVM_VERSION=$(LLVM_VERSION) +LDFLAGS += $(shell $(LLVMPREFIX)/bin/llvm-config --ldflags) +OBJS= hello.o + +$(PASSLIBNAME): $(OBJS) + $(QUIET) $(ECHO) " [LINK] $@" + $(QUIET) $(CXX) $(CFLAGS) -shared -o $@ $(CPPS) $(OBJS) $(LDFLAGS) $(LIBS) + +%.o: %.cpp $(HEADERS) + $(QUIET) $(ECHO) " [C++] $<" + $(QUIET) $(CXX) $(CFLAGS) -c -o $@ $< + +install: $(PASSLIBNAME) + $(QUIET) -mkdir -p ../../bin + $(QUIET) $(CP) $(PASSLIBNAME) ../../bin/$(PASSLIBNAME) + +clean: + -rm -f *.o *.so diff --git a/minix/llvm/passes/hello/hello.cpp b/minix/llvm/passes/hello/hello.cpp new file mode 100644 index 000000000..5d7f9dc6c --- /dev/null +++ b/minix/llvm/passes/hello/hello.cpp @@ -0,0 +1,114 @@ +#include "pass_hello.h" +#include + +using namespace llvm; + +#define DBG(M) M +#define helloPassLog(M) DBG(errs() << "HelloPass: " << M << "\n") +#define MSG "Hello world!" +#define ERROR_FAILURE 1 + +namespace { + + class HelloPass : public ModulePass { + + public: + static char ID; + + + HelloPass() : ModulePass(ID) { } + + + virtual bool runOnModule(Module &M) { + + Function* printfFunction = NULL; + Function* mainFunction = NULL; + + mainFunction = M.getFunction("main"); + if (NULL == mainFunction) + { + helloPassLog("Info: main() not found. Skipping instrumentation."); + return false; + } + + /* Prepare the string arguments for printf */ + std::string printFuncName = "printf" ; + const std::string msg = MSG; + const std::string fmt = "%s\n"; + Constant* strConstMsg = NULL; + Constant* strConstFmt = NULL; + std::vector args(0); + Instruction *I = NULL; + + PassUtil::getStringGlobalVariable(M, fmt, ".fmtStr", "", &strConstFmt, false); + PassUtil::getStringGlobalVariable(M, msg, ".helloworld", "", &strConstMsg, false); + + if (NULL == strConstFmt || NULL == strConstMsg) + { + helloPassLog("Error: Prepared string contants point to NULL"); + exitOnError(ERROR_FAILURE); + } + + args.push_back(strConstFmt); + args.push_back(strConstMsg); + + /* Look for printf declaration */ + std::vector functionTyArgs; + FunctionType* printfFuncType; + + functionTyArgs.push_back(PointerType::get(IntegerType::get(M.getContext(), 8), 0)); + + printfFuncType = PassUtil::getFunctionType(IntegerType::get(M.getContext(), 32), functionTyArgs, true); + if (NULL == printfFuncType) + { + helloPassLog("Error: Couldn't make function-type for printf."); + exitOnError(ERROR_FAILURE); + } + + printfFunction = (Function *) M.getOrInsertFunction(printFuncName, printfFuncType); + if (NULL == printfFunction) + { + helloPassLog("Error: Couldnt find printf function declaration."); + exitOnError(ERROR_FAILURE); + } + + /* Insert call instruction in main() to call printf */ + I = mainFunction->getBasicBlockList().begin()->begin(); + if (NULL != I) + { + if (args.empty()) + { + helloPassLog("Warning: args to printf is empty."); + } + + helloPassLog("Info: Inserting printf call instruction"); + + CallInst* callInst = PassUtil::createCallInstruction(printfFunction, args, "", I); + + if (NULL == callInst ) + { + helloPassLog("Error: callInstr is null."); + exitOnError(ERROR_FAILURE); + } + + helloPassLog("Info: Inserting call instruction successful."); + + return true; + } + + return false; + } + + private: + void exitOnError(int errCode) + { + helloPassLog("Aborting instrumentation."); + exit(errCode); + } + + }; + +} + +char HelloPass::ID = 0; +RegisterPass HP("hello", "Hello Pass", false, false); diff --git a/minix/llvm/passes/hello/pass.h b/minix/llvm/passes/hello/pass.h new file mode 100644 index 000000000..59e542908 --- /dev/null +++ b/minix/llvm/passes/hello/pass.h @@ -0,0 +1,35 @@ + +#ifndef _PASS_H +#define _PASS_H + +#import +#import + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#endif /* _PASS_H */ diff --git a/minix/llvm/passes/hello/pass_hello.h b/minix/llvm/passes/hello/pass_hello.h new file mode 100644 index 000000000..9d1f15e9a --- /dev/null +++ b/minix/llvm/passes/hello/pass_hello.h @@ -0,0 +1,224 @@ +#ifndef _PASS_HELLO_H +#define _PASS_HELLO_H + +#if LLVM_VERSION >= 33 +#define ATTRIBUTE_SET_TY AttributeSet +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else /* LLVM_VERSION < 33 */ +#define ATTRIBUTE_SET_TY AttrListPtr +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif /* LLVM_VERSION >= 33 */ + +#if LLVM_VERSION >= 32 +#define DATA_LAYOUT_TY DataLayout +#define ATTRIBUTE_SET_RET_IDX ATTRIBUTE_SET_TY::ReturnIndex +#define ATTRIBUTE_SET_FN_IDX ATTRIBUTE_SET_TY::FunctionIndex +#include +#if LLVM_VERSION == 32 +#include +#include +#endif +#else /* LLVM_VERSION < 32 */ +#define DATA_LAYOUT_TY TargetData +#define ATTRIBUTE_SET_RET_IDX 0 +#define ATTRIBUTE_SET_FN_IDX (~0U) +#include +#include +#include +#endif /* LLVM_VERSION >= 32 */ + +#if LLVM_VERSION >= 31 +/* XXX Check. */ +#define CONSTANT_ARRAY_INITIALIZER_TY ConstantDataArray + +#else /* LLVM_VERSION < 31 */ +#define CONSTANT_ARRAY_INITIALIZER_TY ConstantArray +#endif /* LLVM_VERSION >= 31 */ + +#if LLVM_VERSION >= 30 +#define BASE_PARSER parser + +#define TYPECONST +#else /* LLVM_VERSION < 30 */ +#define BASE_PARSER basic_parser + +#define TYPECONST const +#endif /* LLVM_VERSION >= 30 */ + +#if LLVM_VERSION >= 29 +#define VALUE_TO_VALUE_MAP_TY ValueToValueMapTy +#else /* LLVM_VERSION < 29 */ +#define VALUE_TO_VALUE_MAP_TY ValueMap +#endif /* LLVM_VERSION >= 29 */ + +#define ZERO_CONSTANT_INT(M) ConstantInt::get((M).getContext(), APInt(32, 0, 10)) +#define VOID_PTR_TY(M) PointerType::get(IntegerType::get((M).getContext(), 8), 0) +#define VOID_PTR_PTR_TY(M) PointerType::get(PointerType::get(IntegerType::get((M).getContext(), 8), 0), 0) + +#define DEBUG_LLVM_DEBUG_API 0 + +typedef enum PassUtilLinkageTypeE { + PASS_UTIL_LINKAGE_NONE = 0, + PASS_UTIL_LINKAGE_WEAK, + PASS_UTIL_LINKAGE_COMMON, + PASS_UTIL_LINKAGE_EXTERNAL, + PASS_UTIL_LINKAGE_EXTERNAL_WEAK, + PASS_UTIL_LINKAGE_WEAK_POINTER, + PASS_UTIL_LINKAGE_PRIVATE, + __NUM_PASS_UTIL_LINKAGE_TYPES + /* Values here should only be appended at the end, external components (e.g., scripts) may be relying on them.*/ +} PassUtilLinkageType; + +#define PASS_UTIL_LINKAGE_TYPE_STRINGS \ + "NONE", \ + "WEAK", \ + "COMMON", \ + "EXTERNAL", \ + "EXTERNAL_WEAK", \ + "WEAK_POINTER", \ + "PRIVATE" + +typedef enum PassUtilPropE { + PASS_UTIL_PROP_NONE, + PASS_UTIL_PROP_NOINLINE, + PASS_UTIL_PROP_USED, + PASS_UTIL_PROP_PRESERVE, + __NUM_PASS_UTIL_PROPS +} PassUtilProp; + +#define PASS_UTIL_FLAG(F) (1 << F) + +#define PASS_COMMON_INIT_ONCE() \ + Module *PassUtil::M = NULL; \ + +using namespace llvm; + +namespace llvm { + +class PassUtil { + public: + static Constant* getGetElementPtrConstant(Constant *constant, std::vector &indexes); + static CallInst* createCallInstruction(Value *F, std::vector &args, const Twine &NameStr="", Instruction *InsertBefore=0); + static CallInst* createCallInstruction(Value *F, std::vector &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0); + static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector &argsTy, bool isVarArg=false); + static Constant* getStringConstantArray(Module &M, const std::string &string); + static GlobalVariable* getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection = "", Constant **getElementPtrExpr=NULL, bool cacheable=false); + private: + static Module *M; +}; + +inline Constant* PassUtil::getGetElementPtrConstant(Constant *constant, std::vector &indexes) { +#if LLVM_VERSION >= 30 + ArrayRef ref(indexes); + return ConstantExpr::getGetElementPtr(constant, ref); +#else + return ConstantExpr::getGetElementPtr(constant, &indexes[0], indexes.size()); +#endif +} + +inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector &args, const Twine &NameStr, Instruction *InsertBefore) { +#if LLVM_VERSION >= 30 + ArrayRef ref(args); + return CallInst::Create(F, ref, NameStr, InsertBefore); +#else + return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertBefore); +#endif +} + +inline CallInst* PassUtil::createCallInstruction(Value *F, std::vector &args, const Twine &NameStr, BasicBlock *InsertAtEnd) { +#if LLVM_VERSION >= 30 + ArrayRef ref(args); + return CallInst::Create(F, ref, NameStr, InsertAtEnd); +#else + return CallInst::Create(F, args.begin(), args.end(), NameStr, InsertAtEnd); +#endif +} + +inline FunctionType* PassUtil::getFunctionType(TYPECONST Type* Result, std::vector &argsTy, bool isVarArg) +{ +#if LLVM_VERSION >= 30 + ArrayRef ref(argsTy); + return FunctionType::get(Result, ref, isVarArg); +#else + return FunctionType::get(Result, argsTy, isVarArg); +#endif +} + + +inline Constant* PassUtil::getStringConstantArray(Module &M, const std::string &string) +{ + std::vector elements; + elements.reserve(string.size() + 1); + for (unsigned i = 0; i < string.size(); ++i) + elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), string[i])); + + // Add a null terminator to the string... + elements.push_back(ConstantInt::get(Type::getInt8Ty(M.getContext()), 0)); + + ArrayType *ATy = ArrayType::get(Type::getInt8Ty(M.getContext()), elements.size()); + return ConstantArray::get(ATy, elements); +} + +inline GlobalVariable* PassUtil::getStringGlobalVariable(Module &M, const std::string &string, const std::string &varName, const std::string &varSection, Constant **getElementPtrExpr, bool cacheable) +{ + static std::map stringCache; + std::map::iterator stringCacheIt; + std::string stringCacheKey; + GlobalVariable *strGV = NULL; + + if (cacheable) { + stringCacheKey = string + "~!~!" + varName + "~!~!" + varSection; + stringCacheIt = stringCache.find(stringCacheKey); + if (stringCacheIt != stringCache.end()) { + strGV = stringCacheIt->second; + cacheable = false; + } + } + + if (!strGV) { + //create a constant internal string reference + Constant *stringValue = PassUtil::getStringConstantArray(M, string); + + //create the global variable, cache it, and record it in the module + strGV = new GlobalVariable(M, stringValue->getType(), true, + GlobalValue::InternalLinkage, stringValue, varName); + if (varSection.compare("")) { + strGV->setSection(varSection); + } + } + if (getElementPtrExpr) { + std::vector strConstantIndices; + strConstantIndices.push_back(ZERO_CONSTANT_INT(M)); + strConstantIndices.push_back(ZERO_CONSTANT_INT(M)); + *getElementPtrExpr = PassUtil::getGetElementPtrConstant(strGV, strConstantIndices); + } + + if (cacheable) { + stringCache.insert(std::pair(stringCacheKey, strGV)); + } + + return strGV; +} + +} + +#endif /* _PASS_HELLO_H */ diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk index 208e74867..4de947a63 100644 --- a/share/mk/bsd.own.mk +++ b/share/mk/bsd.own.mk @@ -61,7 +61,7 @@ MKRUMP:= no MKSKEY:= no MKYP:= no -WEAKALIASOVERRIDEPASS?=${NETBSDSRCDIR}/minix/llvm/bin/weak-alias-module-override +WEAKALIASOVERRIDEPASS?=${NETBSDSRCDIR}/minix/llvm/bin/weak-alias-module-override.so GOLD_PLUGIN?=${NETBSDSRCDIR}/minix/llvm/bin/LLVMgold.so # By default when running LLVM passes: @@ -69,6 +69,7 @@ GOLD_PLUGIN?=${NETBSDSRCDIR}/minix/llvm/bin/LLVMgold.so # - run the passe which allows assembly weak symbols to be # overriden by bitcode functions OPTFLAGS?= -disable-opt \ + -disable-internalize -disable-inlining \ -load ${WEAKALIASOVERRIDEPASS} -weak-alias-module-override # Whitout -Wl,--no-ctors-in-init-array, golds moves the constructors out of -- 2.44.0