diff options
author | Dan Liew <daniel.liew@imperial.ac.uk> | 2016-11-25 08:55:04 +0000 |
---|---|---|
committer | Dan Liew <daniel.liew@imperial.ac.uk> | 2017-02-21 21:32:52 +0000 |
commit | 70715151746a24c4c6919292956111b00fcd3a26 (patch) | |
tree | d7cd3c59f4e8f68f106ab638f1dad8ebfa09b1a7 /lib/Module/ModuleUtil.cpp | |
parent | 17705a0ecea3d5c6ad74587cc76adf92e6e8be6d (diff) | |
download | klee-70715151746a24c4c6919292956111b00fcd3a26.tar.gz |
Teach `klee::getDirectCallTarget()` to resolve weak aliases. This is
controlled by a new parameter `moduleIsFullyLinked`. When true the linkage type of a weak alias is ignored. It is legal to do this when the module is fully linked because there won't be another function that could override the weak alias. This fixes a previous assertion failure in `klee::getDirectCallTarget()` triggered by the `test/regression/2016-11-24-bitcast-weak-alias.c` test case.
Diffstat (limited to 'lib/Module/ModuleUtil.cpp')
-rw-r--r-- | lib/Module/ModuleUtil.cpp | 42 |
1 files changed, 26 insertions, 16 deletions
diff --git a/lib/Module/ModuleUtil.cpp b/lib/Module/ModuleUtil.cpp index a5394067..2cd41c89 100644 --- a/lib/Module/ModuleUtil.cpp +++ b/lib/Module/ModuleUtil.cpp @@ -436,23 +436,33 @@ Module *klee::linkWithLibrary(Module *module, #endif } - - -Function *klee::getDirectCallTarget(CallSite cs) { +Function *klee::getDirectCallTarget(CallSite cs, bool moduleIsFullyLinked) { Value *v = cs.getCalledValue(); - if (Function *f = dyn_cast<Function>(v)) { - return f; - } else if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(v)) { - if (ce->getOpcode()==Instruction::BitCast) - if (Function *f = dyn_cast<Function>(ce->getOperand(0)->stripPointerCasts())) - return f; - - // NOTE: This assert may fire, it isn't necessarily a problem and - // can be disabled, I just wanted to know when and if it happened. - assert(0 && "FIXME: Unresolved direct target for a constant expression."); - } - - return 0; + bool viaConstantExpr = false; + // Walk through aliases and bitcasts to try to find + // the function being called. + do { + if (Function *f = dyn_cast<Function>(v)) { + return f; + } else if (llvm::GlobalAlias *ga = dyn_cast<GlobalAlias>(v)) { + if (moduleIsFullyLinked || !(ga->mayBeOverridden())) { + v = ga->getAliasee(); + } else { + v = NULL; + } + } else if (llvm::ConstantExpr *ce = dyn_cast<llvm::ConstantExpr>(v)) { + viaConstantExpr = true; + v = ce->getOperand(0)->stripPointerCasts(); + } else { + v = NULL; + } + } while (v != NULL); + + // NOTE: This assert may fire, it isn't necessarily a problem and + // can be disabled, I just wanted to know when and if it happened. + assert((!viaConstantExpr) && + "FIXME: Unresolved direct target for a constant expression"); + return NULL; } static bool valueIsOnlyCalled(const Value *v) { |