00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "ExternalDispatcher.h"
00011
00012 #include "llvm/Module.h"
00013 #include "llvm/Constants.h"
00014 #include "llvm/DerivedTypes.h"
00015 #include "llvm/Instructions.h"
00016 #include "llvm/ModuleProvider.h"
00017 #include "llvm/ExecutionEngine/JIT.h"
00018 #include "llvm/ExecutionEngine/GenericValue.h"
00019 #include "llvm/Support/CallSite.h"
00020 #include "llvm/System/DynamicLibrary.h"
00021 #include "llvm/Support/Streams.h"
00022 #include "llvm/Support/raw_ostream.h"
00023 #include <setjmp.h>
00024 #include <signal.h>
00025
00026 using namespace llvm;
00027 using namespace klee;
00028
00029
00030
00031 static jmp_buf escapeCallJmpBuf;
00032
00033 extern "C" {
00034
00035 static void sigsegv_handler(int signal, siginfo_t *info, void *context) {
00036 longjmp(escapeCallJmpBuf, 1);
00037 }
00038
00039 }
00040
00041 void *ExternalDispatcher::resolveSymbol(const std::string &name) {
00042 assert(executionEngine);
00043
00044 const char *str = name.c_str();
00045
00046
00047
00048
00049
00050
00051 if (str[0] == 1)
00052 ++str;
00053
00054 void *addr = dl_symbols.SearchForAddressOfSymbol(str);
00055 if (addr)
00056 return addr;
00057
00058
00059
00060 if (name[0] == 1 && str[0]=='_') {
00061 ++str;
00062 addr = dl_symbols.SearchForAddressOfSymbol(str);
00063 }
00064
00065 return addr;
00066 }
00067
00068 ExternalDispatcher::ExternalDispatcher() {
00069 dispatchModule = new Module("ExternalDispatcher");
00070 ExistingModuleProvider* MP = new ExistingModuleProvider(dispatchModule);
00071
00072 std::string error;
00073 executionEngine = ExecutionEngine::createJIT(MP, &error);
00074 if (!executionEngine) {
00075 llvm::cerr << "unable to make jit: " << error << "\n";
00076 abort();
00077 }
00078
00079
00080 if (executionEngine) {
00081
00082
00083 dl_symbols.LoadLibraryPermanently(0);
00084 }
00085
00086 #ifdef WINDOWS
00087 preboundFunctions["getpid"] = (void*) (long) getpid;
00088 preboundFunctions["putchar"] = (void*) (long) putchar;
00089 preboundFunctions["printf"] = (void*) (long) printf;
00090 preboundFunctions["fprintf"] = (void*) (long) fprintf;
00091 preboundFunctions["sprintf"] = (void*) (long) sprintf;
00092 #endif
00093 }
00094
00095 ExternalDispatcher::~ExternalDispatcher() {
00096 delete executionEngine;
00097 }
00098
00099 bool ExternalDispatcher::executeCall(Function *f, Instruction *i, uint64_t *args) {
00100 dispatchers_ty::iterator it = dispatchers.find(i);
00101 Function *dispatcher;
00102
00103 if (it == dispatchers.end()) {
00104 #ifdef WINDOWS
00105 std::map<std::string, void*>::iterator it2 =
00106 preboundFunctions.find(f->getName()));
00107
00108 if (it2 != preboundFunctions.end()) {
00109
00110 if (it2->second) {
00111 executionEngine->addGlobalMapping(f, it2->second);
00112 it2->second = 0;
00113 }
00114 }
00115 #endif
00116
00117 dispatcher = createDispatcher(f,i);
00118
00119 dispatchers.insert(std::make_pair(i, dispatcher));
00120
00121 if (dispatcher) {
00122
00123
00124
00125
00126 executionEngine->recompileAndRelinkFunction(dispatcher);
00127 }
00128 } else {
00129 dispatcher = it->second;
00130 }
00131
00132 return runProtectedCall(dispatcher, args);
00133 }
00134
00135
00136 static uint64_t *gTheArgsP;
00137
00138 bool ExternalDispatcher::runProtectedCall(Function *f, uint64_t *args) {
00139 struct sigaction segvAction, segvActionOld;
00140 bool res;
00141
00142 if (!f)
00143 return false;
00144
00145 std::vector<GenericValue> gvArgs;
00146 gTheArgsP = args;
00147
00148 segvAction.sa_handler = 0;
00149 memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask));
00150 segvAction.sa_flags = SA_SIGINFO;
00151 segvAction.sa_sigaction = ::sigsegv_handler;
00152 sigaction(SIGSEGV, &segvAction, &segvActionOld);
00153
00154 if (setjmp(escapeCallJmpBuf)) {
00155 res = false;
00156 } else {
00157 executionEngine->runFunction(f, gvArgs);
00158 res = true;
00159 }
00160
00161 sigaction(SIGSEGV, &segvActionOld, 0);
00162 return res;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172 Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *inst) {
00173 if (!resolveSymbol(target->getName()))
00174 return 0;
00175
00176 CallSite cs;
00177 if (inst->getOpcode()==Instruction::Call) {
00178 cs = CallSite(cast<CallInst>(inst));
00179 } else {
00180 cs = CallSite(cast<InvokeInst>(inst));
00181 }
00182
00183 Value **args = new Value*[cs.arg_size()];
00184
00185 std::vector<const Type*> nullary;
00186
00187 Function *dispatcher = Function::Create(FunctionType::get(Type::VoidTy,
00188 nullary, false),
00189 GlobalVariable::ExternalLinkage,
00190 "",
00191 dispatchModule);
00192
00193
00194 BasicBlock *dBB = BasicBlock::Create("entry", dispatcher);
00195
00196 Instruction *argI64sp = new IntToPtrInst(ConstantInt::get(Type::Int64Ty, (long) (void*) &gTheArgsP),
00197 PointerType::getUnqual(PointerType::getUnqual(Type::Int64Ty)),
00198 "argsp",
00199 dBB);
00200 Instruction *argI64s = new LoadInst(argI64sp, "args", dBB);
00201
00202 unsigned i = 0;
00203 for (CallSite::arg_iterator ai = cs.arg_begin(), ae = cs.arg_end();
00204 ai!=ae; ++ai, ++i) {
00205 Value *index = ConstantInt::get(Type::Int32Ty, i+1);
00206
00207 Instruction *argI64p = GetElementPtrInst::Create(argI64s, index, "", dBB);
00208 Instruction *argp = new BitCastInst(argI64p,
00209 PointerType::getUnqual((*ai)->getType()), "", dBB);
00210 args[i] = new LoadInst(argp, "", dBB);
00211 }
00212
00213 Instruction *result = CallInst::Create(target, args, args+i, "", dBB);
00214
00215 if (result->getType() != Type::VoidTy) {
00216 Instruction *resp = new BitCastInst(argI64s,
00217 PointerType::getUnqual(result->getType()), "", dBB);
00218 new StoreInst(result, resp, dBB);
00219 }
00220
00221 ReturnInst::Create(dBB);
00222
00223 delete[] args;
00224
00225 return dispatcher;
00226 }