blob: fc13a10855b6f2c19dd27a99231636472134346a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
//===-- Callback.cpp - Trap handler for function resolution ---------------===//
//
// This file defines the SIGSEGV handler which is invoked when a reference to a
// non-codegen'd function is found.
//
//===----------------------------------------------------------------------===//
#include "VM.h"
#include "Support/Statistic.h"
#include <iostream>
static VM *TheVM = 0;
// CompilationCallback - Invoked the first time that a call site is found,
// which causes lazy compilation of the target function.
//
void VM::CompilationCallback() {
#if defined(i386) || defined(__i386__) || defined(__x86__)
unsigned *StackPtr = (unsigned*)__builtin_frame_address(0);
unsigned RetAddr = (unsigned)__builtin_return_address(0);
assert(StackPtr[1] == RetAddr &&
"Could not find return address on the stack!");
// The call instruction should have pushed the return value onto the stack...
RetAddr -= 4; // Backtrack to the reference itself...
DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << RetAddr
<< " ESP=0x" << (unsigned)StackPtr << std::dec
<< ": Resolving call to function: "
<< TheVM->getFunctionReferencedName((void*)RetAddr) << "\n");
// Sanity check to make sure this really is a call instruction...
assert(((unsigned char*)RetAddr)[-1] == 0xE8 && "Not a call instr!");
unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RetAddr);
// Rewrite the call target... so that we don't fault every time we execute
// the call.
*(unsigned*)RetAddr = NewVal-RetAddr-4;
// Change the return address to reexecute the call instruction...
StackPtr[1] -= 5;
#else
abort();
#endif
}
void VM::registerCallback() {
TheVM = this;
}
|