2017-04-29 17:15:03 +04:00

117 строки
2.9 KiB
C++

/*
* This is a dependency for a few of the passes. Collects
* call sites and organizes them by TargetCallType.
*
*/
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "llvm/Pass.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/CallSite.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
#include <iostream>
#include <fstream>
#include <json/config.h>
#include <json/value.h>
#include <json/reader.h>
using namespace llvm;
#include "TargetCallSitesPass.h"
#include "../Transform/FunctionExternalizer.h"
void
TargetCallSitesPass::getAnalysisUsage(AnalysisUsage &AU) const
{
}
void
TargetCallSitesPass::parseConfig(std::string configFilePath, TargetCallType tct,
Module *M)
{
Json::Value dict;
std::ifstream strm;
// XXX quite trusting
strm.open(configFilePath);
strm >> dict;
strm.close();
Json::Value::Members mems = dict.getMemberNames();
for (auto memIt = mems.begin(); memIt != mems.end(); ++memIt) {
std::string fnName = *memIt;
int argIdx = dict[fnName].asInt();
assert(argIdx >= -1 && "Argument index should be >= -1");
/*
* Determine if the name given for the function in the config is
* a name of a function in this module.
*/
Function *fp = M->getFunction(fnName);
if (fp == NULL) {
continue;
}
/*
* See if argument counts match up
* If we were cool, we would check arg types if we detected
* no name mangling.
*
* The difference between sink and source cases is that at some point
* want to not just handle return value of source but allow for in/out
* or out arguments to be tainted.
*/
if (argIdx != -1 && \
(fp->arg_size() == 0 || fp->arg_size() <= (unsigned)argIdx)) {
continue;
}
/*
* Check this Function's User list. If there is no instruction using
* this function, then we have nothing to check for it.
*/
if (fp->user_empty() == true) {
continue;
}
/* Ok, so we have name, argument, function, and a non-empty user list */
for (auto userIt = fp->user_begin(); userIt != fp->user_end();
++userIt) {
User *targUser = *userIt;
/*
* Not handling functions passed call backs or entry pts based on
* RT environment, so just get CallSites. Then make sure the called
* function is the targeted function (from config file)
*/
if (!isa<CallInst>(targUser) && !isa<InvokeInst>(targUser)) {
continue;
}
Instruction *targInst = cast<Instruction>(targUser);
std::unique_ptr<TargetCallSite> tcs(new TargetCallSite(targInst,
argIdx));
targetCallMap[tct].push_back(std::move(tcs));
}
}
}
bool
TargetCallSitesPass::runOnModule(Module &M)
{
errs() << "Running target call sites pass.\n";
for (auto k = targetConfigMap.begin(); k != targetConfigMap.end(); ++k) {
TargetCallType t = k->first;
std::string p = k->second;
parseConfig(p, t, &M);
}
return false;
}
char TargetCallSitesPass::ID = 0;
static RegisterPass<TargetCallSitesPass> XX("target-call-sites", "");