1 //===-- Callback.cpp - Trap handler for function resolution ---------------===//
3 // This file defines the SIGSEGV handler which is invoked when a reference to a
4 // non-codegen'd function is found.
6 //===----------------------------------------------------------------------===//
9 #include "Support/Statistic.h"
16 static void TrapHandler(int TN, siginfo_t *SI, ucontext_t *ucp) {
17 assert(TN == SIGSEGV && "Should be SIGSEGV!");
19 #ifdef REG_EIP /* this code does not compile on Sparc! */
20 if (SI->si_code != SEGV_MAPERR || SI->si_addr != 0 ||
21 ucp->uc_mcontext.gregs[REG_EIP] != 0) {
22 std::cerr << "Bad SEGV encountered!\n";
26 // The call instruction should have pushed the return value onto the stack...
27 unsigned RefAddr = *(unsigned*)ucp->uc_mcontext.gregs[REG_ESP];
28 RefAddr -= 4; // Backtrack to the reference itself...
30 DEBUG(std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr
31 << " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec
32 << ": Resolving call to function: "
33 << TheVM->getFunctionReferencedName((void*)RefAddr) << "\n");
35 // Sanity check to make sure this really is a call instruction...
36 assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!");
38 unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RefAddr);
40 // Rewrite the call target... so that we don't fault every time we execute
42 *(unsigned*)RefAddr = NewVal-RefAddr-4;
44 // Change the instruction pointer to be the real target of the call...
45 ucp->uc_mcontext.gregs[REG_EIP] = NewVal;
51 void VM::registerCallback() {
54 // Register the signal handler...
56 SA.sa_sigaction = (void (*)(int, siginfo_t*, void*))TrapHandler;
57 sigfillset(&SA.sa_mask); // Block all signals while codegen'ing
58 SA.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; // Get siginfo
59 sigaction(SIGSEGV, &SA, 0); // Install the handler