LLVM Hello pass: inserts printf statement in main() method.

This commit is contained in:
Koustubha Bhat 2014-06-06 16:20:39 +02:00 committed by Lionel Sambuc
parent 5ba302fdea
commit dd85959391
7 changed files with 404 additions and 2 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,114 @@
#include "pass_hello.h"
#include <stdlib.h>
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<Value*> 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<TYPECONST Type*> 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<HelloPass> HP("hello", "Hello Pass", false, false);

View file

@ -0,0 +1,35 @@
#ifndef _PASS_H
#define _PASS_H
#import <set>
#import <map>
#include <llvm/Pass.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/Analysis/AliasAnalysis.h>
#include <llvm/Support/Debug.h>
#include <llvm/Transforms/Utils/Cloning.h>
#include <llvm/ADT/Statistic.h>
#include <llvm/Support/Regex.h>
#include <llvm/Assembly/Writer.h>
#include <llvm/Support/CallSite.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Analysis/LoopInfo.h>
#include <llvm/Support/InstIterator.h>
#include <llvm/Transforms/Utils/Local.h>
#include <llvm/Transforms/Scalar.h>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <common/pass_common.h>
#endif /* _PASS_H */

View file

@ -0,0 +1,224 @@
#ifndef _PASS_HELLO_H
#define _PASS_HELLO_H
#if LLVM_VERSION >= 33
#define ATTRIBUTE_SET_TY AttributeSet
#include <llvm/IR/Function.h>
#include <llvm/IR/Module.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Constants.h>
#include <llvm/IR/Intrinsics.h>
#include <llvm/IR/DerivedTypes.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/IntrinsicInst.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/Support/raw_ostream.h>
#else /* LLVM_VERSION < 33 */
#define ATTRIBUTE_SET_TY AttrListPtr
#include <llvm/Function.h>
#include <llvm/Module.h>
#include <llvm/Instructions.h>
#include <llvm/Type.h>
#include <llvm/Constants.h>
#include <llvm/Intrinsics.h>
#include <llvm/DerivedTypes.h>
#include <llvm/LLVMContext.h>
#include <llvm/IntrinsicInst.h>
#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 <llvm/DebugInfo.h>
#if LLVM_VERSION == 32
#include <llvm/DataLayout.h>
#include <llvm/IRBuilder.h>
#endif
#else /* LLVM_VERSION < 32 */
#define DATA_LAYOUT_TY TargetData
#define ATTRIBUTE_SET_RET_IDX 0
#define ATTRIBUTE_SET_FN_IDX (~0U)
#include <llvm/Target/TargetData.h>
#include <llvm/Analysis/DebugInfo.h>
#include <llvm/Support/IRBuilder.h>
#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<const Value*, Value*>
#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<Value*> &indexes);
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", Instruction *InsertBefore=0);
static CallInst* createCallInstruction(Value *F, std::vector<Value*> &args, const Twine &NameStr="", BasicBlock *InsertAtEnd=0);
static FunctionType* getFunctionType(TYPECONST Type* Result, std::vector<TYPECONST Type*> &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<Value*> &indexes) {
#if LLVM_VERSION >= 30
ArrayRef<Value*> 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<Value*> &args, const Twine &NameStr, Instruction *InsertBefore) {
#if LLVM_VERSION >= 30
ArrayRef<Value*> 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<Value*> &args, const Twine &NameStr, BasicBlock *InsertAtEnd) {
#if LLVM_VERSION >= 30
ArrayRef<Value*> 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<TYPECONST Type*> &argsTy, bool isVarArg)
{
#if LLVM_VERSION >= 30
ArrayRef<TYPECONST Type*> 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<Constant*> 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<std::string, GlobalVariable*> stringCache;
std::map<std::string, GlobalVariable*>::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<Value*> 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<std::string, GlobalVariable*>(stringCacheKey, strGV));
}
return strGV;
}
}
#endif /* _PASS_HELLO_H */

View file

@ -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