16#include "llvm/IR/GlobalAlias.h"
17#include "llvm/Support/CommandLine.h"
18#include "llvm/Support/Regex.h"
25 FunctionAlias(
"function-alias",
26 cl::desc(
"Replace functions that match name or regular "
27 "expression pattern with an alias to the function "
28 "whose name is given by replacement"),
29 cl::value_desc(
"name|pattern>:<replacement"),
37 bool modified =
false;
39 assert((M.ifunc_size() == 0) &&
"Unexpected ifunc");
41 for (
const auto &pair : FunctionAlias) {
42 bool matchFound =
false;
46 std::size_t lastColon = pair.rfind(
':');
47 if (lastColon == std::string::npos) {
48 klee_error(
"function-alias: no replacement given");
50 std::string pattern = pair.substr(0, lastColon);
51 std::string replacement = pair.substr(lastColon + 1);
54 klee_error(
"function-alias: name or pattern cannot be empty");
55 if (replacement.empty())
56 klee_error(
"function-alias: replacement cannot be empty");
58 if (pattern == replacement) {
59 klee_error(
"function-alias: @%s cannot replace itself", pattern.c_str());
63 GlobalValue *replacementValue = M.getNamedValue(replacement);
65 klee_error(
"function-alias: replacement function @%s could not be found",
69 GlobalValue *match = M.getNamedValue(pattern);
73 klee_message(
"function-alias: replaced @%s with @%s", pattern.c_str(),
78 if (match !=
nullptr) {
80 klee_error(
"function-alias: no (replacable) match for '%s' found",
86 if (!regex.isValid(error)) {
87 klee_error(
"function-alias: '%s' is not a valid regex: %s",
88 pattern.c_str(), error.c_str());
91 std::vector<GlobalValue *> matches;
94 for (GlobalValue &global : M.global_values()) {
95 if (!global.hasName())
101 SmallVector<StringRef, 8> matchVec;
102 bool match = regex.match(global.getName(), &matchVec);
103 if (match && matchVec[0].str() == global.getName().str()) {
104 if (global.getName().str() == replacement) {
105 klee_warning(
"function-alias: do not replace @%s (matching '%s') "
106 "with @%s: cannot replace itself",
107 global.getName().str().c_str(), pattern.c_str(),
108 replacement.c_str());
111 matches.push_back(&global);
116 for (GlobalValue *global : matches) {
118 std::string name = global->getName().str();
122 klee_message(
"function-alias: replaced @%s (matching '%s') with @%s",
123 name.c_str(), pattern.c_str(), replacement.c_str());
128 klee_error(
"function-alias: no (replacable) match for '%s' found",
137 const Type *type = gv->getType();
138 while (type->isPointerTy()) {
139 const PointerType *ptr = cast<PointerType>(type);
140 type = ptr->getElementType();
142 return cast<FunctionType>(type);
146 const GlobalValue *replacement) {
149 assert(MFT !=
nullptr && RFT !=
nullptr);
151 if (MFT->getReturnType() != RFT->getReturnType()) {
152 klee_warning(
"function-alias: @%s could not be replaced with @%s: "
153 "return type differs",
154 match->getName().str().c_str(),
155 replacement->getName().str().c_str());
159 if (MFT->isVarArg() != RFT->isVarArg()) {
160 klee_warning(
"function-alias: @%s could not be replaced with @%s: "
161 "one has varargs while the other does not",
162 match->getName().str().c_str(),
163 replacement->getName().str().c_str());
167 if (MFT->getNumParams() != RFT->getNumParams()) {
168 klee_warning(
"function-alias: @%s could not be replaced with @%s: "
169 "number of parameters differs",
170 match->getName().str().c_str(),
171 replacement->getName().str().c_str());
175 std::size_t numParams = MFT->getNumParams();
176 for (std::size_t i = 0; i < numParams; ++i) {
177 if (MFT->getParamType(i) != RFT->getParamType(i)) {
178 klee_warning(
"function-alias: @%s could not be replaced with @%s: "
179 "parameter types differ",
180 match->getName().str().c_str(),
181 replacement->getName().str().c_str());
189 GlobalValue *replacement) {
193 GlobalAlias *alias = GlobalAlias::create(
"", replacement);
194 match->replaceAllUsesWith(alias);
195 alias->takeName(match);
196 match->eraseFromParent();
202 if (isa_and_nonnull<Function>(gv))
205 if (
const auto *ga = dyn_cast_or_null<GlobalAlias>(gv)) {
206 const auto *aliasee = dyn_cast<GlobalValue>(ga->getAliasee());
209 const auto *cexpr = dyn_cast<ConstantExpr>(ga->getAliasee());
210 if (!cexpr || !cexpr->isCast())
212 aliasee = dyn_cast<GlobalValue>(cexpr->getOperand(0));
static const llvm::FunctionType * getFunctionType(const llvm::GlobalValue *gv)
static bool checkType(const llvm::GlobalValue *match, const llvm::GlobalValue *replacement)
bool runOnModule(llvm::Module &M) override
static bool isFunctionOrGlobalFunctionAlias(const llvm::GlobalValue *gv)
static bool tryToReplace(llvm::GlobalValue *match, llvm::GlobalValue *replacement)
void klee_message(const char *msg,...) __attribute__((format(printf
void klee_error(const char *msg,...) __attribute__((format(printf
llvm::cl::OptionCategory ModuleCat
void void void klee_warning(const char *msg,...) __attribute__((format(printf