 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
67.4% |
31 / 46 |
| Generated: |
2009-05-17 22:47 |
|
Branches Executed: |
82.6% |
38 / 46 |
| |
|
Line Coverage: |
89.2% |
66 / 74 |
| |
 |
|
 |
1 : /* -*- mode: c++; c-basic-offset: 2; -*- */
2 :
3 : #include "ExternalDispatcher.h"
4 :
5 : #include "llvm/Module.h"
6 : #include "llvm/Constants.h"
7 : #include "llvm/DerivedTypes.h"
8 : #include "llvm/Instructions.h"
9 : #include "llvm/ModuleProvider.h"
10 : #include "llvm/ExecutionEngine/JIT.h"
11 : #include "llvm/ExecutionEngine/GenericValue.h"
12 : #include "llvm/Support/CallSite.h"
13 : #include "llvm/System/DynamicLibrary.h"
14 : #include "llvm/Support/Streams.h"
15 : #include "llvm/Support/raw_ostream.h"
16 : #include <setjmp.h>
17 : #include <signal.h>
18 :
19 : using namespace llvm;
20 : using namespace klee;
21 :
22 : /***/
23 :
24 : static jmp_buf escapeCallJmpBuf;
25 :
26 : extern "C" {
27 :
28 0: static void sigsegv_handler(int signal, siginfo_t *info, void *context) {
29 0: longjmp(escapeCallJmpBuf, 1);
30 : }
31 :
32 : }
33 :
34 94: void *ExternalDispatcher::resolveSymbol(const std::string &name) {
0: branch 0 not taken
94: branch 1 taken
35 94: assert(executionEngine);
36 :
37 94: const char *str = name.c_str();
38 :
39 : // We use this to validate that function names can be resolved so we
40 : // need to match how the JIT does it. Unfortunately we can't
41 : // directly access the JIT resolution function
42 : // JIT::getPointerToNamedFunction so we emulate the important points.
43 :
0: branch 0 not taken
94: branch 1 taken
44 94: if (str[0] == 1) // asm specifier, skipped
45 0: ++str;
46 :
47 94: void *addr = dl_symbols.SearchForAddressOfSymbol(str);
92: branch 0 taken
2: branch 1 taken
48 94: if (addr)
49 92: return addr;
50 :
51 : // If it has an asm specifier and starts with an underscore we retry
52 : // without the underscore. I (DWD) don't know why.
0: branch 0 not taken
2: branch 1 taken
2: branch 2 taken
2: branch 3 taken
0: branch 4 not taken
2: branch 5 taken
53 2: if (name[0] == 1 && str[0]=='_') {
54 0: ++str;
55 0: addr = dl_symbols.SearchForAddressOfSymbol(str);
56 : }
57 :
58 2: return addr;
59 : }
60 :
61 206: ExternalDispatcher::ExternalDispatcher() {
62 103: dispatchModule = new Module("ExternalDispatcher");
63 206: ExistingModuleProvider* MP = new ExistingModuleProvider(dispatchModule);
64 :
65 : std::string error;
66 103: executionEngine = ExecutionEngine::createJIT(MP, &error);
0: branch 0 not taken
103: branch 1 taken
103: branch 2 taken
103: branch 3 taken
67 103: if (!executionEngine) {
68 : llvm::cerr << "unable to make jit: " << error << "\n";
69 0: abort();
70 : }
71 :
72 : // from ExecutionEngine::create
103: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
0: branch 3 not taken
73 103: if (executionEngine) {
74 : // Make sure we can resolve symbols in the program as well. The zero arg
75 : // to the function tells DynamicLibrary to load the program, not a library.
76 : try {
77 103: dl_symbols.LoadLibraryPermanently(0);
78 : } catch (...) {
79 : assert(0 && "Exception in LoadLibraryPermantently.\n");
80 : }
81 103: }
82 :
83 : #ifdef WINDOWS
84 : preboundFunctions["getpid"] = (void*) (long) getpid;
85 : preboundFunctions["putchar"] = (void*) (long) putchar;
86 : preboundFunctions["printf"] = (void*) (long) printf;
87 : preboundFunctions["fprintf"] = (void*) (long) fprintf;
88 : preboundFunctions["sprintf"] = (void*) (long) sprintf;
89 : #endif
90 103: }
91 :
92 103: ExternalDispatcher::~ExternalDispatcher() {
103: branch 0 taken
0: branch 1 not taken
103: branch 3 taken
103: branch 4 taken
93 103: delete executionEngine;
94 309: }
95 :
96 288: bool ExternalDispatcher::executeCall(Function *f, Instruction *i, uint64_t *args) {
97 288: dispatchers_ty::iterator it = dispatchers.find(i);
98 : Function *dispatcher;
99 :
84: branch 0 taken
204: branch 1 taken
100 576: if (it == dispatchers.end()) {
101 : #ifdef WINDOWS
102 : let(it2, preboundFunctions.find(f->getName()));
103 :
104 : if (it2 != preboundFunctions.end()) {
105 : // only bind once
106 : if (it2->second) {
107 : executionEngine->addGlobalMapping(f, it2->second);
108 : it2->second = 0;
109 : }
110 : }
111 : #endif
112 :
113 84: dispatcher = createDispatcher(f,i);
114 :
115 168: dispatchers.insert(std::make_pair(i, dispatcher));
116 :
83: branch 0 taken
1: branch 1 taken
117 84: if (dispatcher) {
118 : // force the JIT execution engine to go ahead and build the
119 : // function. this ensures that any errors or assertions in the
120 : // compilation process will trigger crashes instead of being
121 : // caught as aborts in the external function.
122 83: executionEngine->recompileAndRelinkFunction(dispatcher);
123 : }
124 : } else {
125 204: dispatcher = it->second;
126 : }
127 :
128 288: return runProtectedCall(dispatcher, args);
129 : }
130 :
131 : // XXX not reentrant
132 : static uint64_t *gTheArgsP;
133 :
134 288: bool ExternalDispatcher::runProtectedCall(Function *f, uint64_t *args) {
135 : struct sigaction segvAction, segvActionOld;
136 : bool res;
137 :
1: branch 0 taken
287: branch 1 taken
138 288: if (!f)
139 1: return false;
140 :
141 : std::vector<GenericValue> gvArgs;
142 287: gTheArgsP = args;
143 :
144 287: segvAction.sa_handler = 0;
145 : memset(&segvAction.sa_mask, 0, sizeof(segvAction.sa_mask));
146 287: segvAction.sa_flags = SA_SIGINFO;
147 287: segvAction.sa_sigaction = ::sigsegv_handler;
148 287: sigaction(SIGSEGV, &segvAction, &segvActionOld);
149 :
0: branch 1 not taken
287: branch 2 taken
150 287: if (setjmp(escapeCallJmpBuf)) {
151 0: res = false;
152 : } else {
153 287: executionEngine->runFunction(f, gvArgs);
154 287: res = true;
155 : }
156 :
157 287: sigaction(SIGSEGV, &segvActionOld, 0);
158 287: return res;
159 : }
160 :
161 : // for performance purposes we construct the stub in such a way that
162 : // the arguments pointer is passed through the static global variable
163 : // gTheArgsP in this file. This is done so that the stub function
164 : // prototype trivially matches the special cases that the JIT knows
165 : // how to directly call. If this is not done, then the jit will end up
166 : // generating a nullary stub just to call our stub, for every single
167 : // function call.
168 84: Function *ExternalDispatcher::createDispatcher(Function *target, Instruction *inst) {
1: branch 2 taken
83: branch 3 taken
169 168: if (!resolveSymbol(target->getName()))
170 1: return 0;
171 :
172 : CallSite cs;
83: branch 0 taken
0: branch 1 not taken
173 166: if (inst->getOpcode()==Instruction::Call) {
174 83: cs = CallSite(cast<CallInst>(inst));
175 : } else {
176 0: cs = CallSite(cast<InvokeInst>(inst));
177 : }
178 :
179 83: Value **args = new Value*[cs.arg_size()];
180 :
181 : std::vector<const Type*> nullary;
182 :
183 : Function *dispatcher = Function::Create(FunctionType::get(Type::VoidTy,
184 : nullary, false),
185 : GlobalVariable::ExternalLinkage,
186 : "",
187 249: dispatchModule);
188 :
189 :
190 166: BasicBlock *dBB = BasicBlock::Create("entry", dispatcher);
191 :
192 : Instruction *argI64sp = new IntToPtrInst(ConstantInt::get(Type::Int64Ty, (long) (void*) &gTheArgsP),
193 : PointerType::getUnqual(PointerType::getUnqual(Type::Int64Ty)),
194 : "argsp",
195 415: dBB);
196 83: Instruction *argI64s = new LoadInst(argI64sp, "args", dBB);
197 :
198 83: unsigned i = 0;
138: branch 1 taken
83: branch 2 taken
199 304: for (CallSite::arg_iterator ai = cs.arg_begin(), ae = cs.arg_end();
200 : ai!=ae; ++ai, ++i) {
201 138: Value *index = ConstantInt::get(Type::Int32Ty, i+1);
202 :
203 276: Instruction *argI64p = GetElementPtrInst::Create(argI64s, index, "", dBB);
204 : Instruction *argp = new BitCastInst(argI64p,
205 414: PointerType::getUnqual((*ai)->getType()), "", dBB);
206 276: args[i] = new LoadInst(argp, "", dBB);
207 : }
208 :
209 166: Instruction *result = CallInst::Create(target, args, args+i, "", dBB);
210 :
83: branch 0 taken
0: branch 1 not taken
211 166: if (result->getType() != Type::VoidTy) {
212 : Instruction *resp = new BitCastInst(argI64s,
213 332: PointerType::getUnqual(result->getType()), "", dBB);
214 83: new StoreInst(result, resp, dBB);
215 : }
216 :
217 : ReturnInst::Create(dBB);
218 :
83: branch 0 taken
0: branch 1 not taken
219 83: delete[] args;
220 :
221 83: return dispatcher;
103: branch 0 taken
0: branch 1 not taken
103: branch 2 taken
0: branch 3 not taken
222 206: }
Generated: 2009-05-17 22:47 by zcov