blob: b843e106895055d4f1191081e43eb52bf0651cda [file] [log] [blame]
Chris Lattnerbd199fb2002-12-24 00:01:05 +00001//===-- Callback.cpp - Trap handler for function resolution ---------------===//
2//
3// This file defines the SIGSEGV handler which is invoked when a reference to a
4// non-codegen'd function is found.
5//
6//===----------------------------------------------------------------------===//
7
8#include "VM.h"
9#include "Support/Statistic.h"
10#include <signal.h>
11#include <ucontext.h>
12#include <iostream>
13
14static VM *TheVM = 0;
15
16static void TrapHandler(int TN, siginfo_t *SI, ucontext_t *ucp) {
17 assert(TN == SIGSEGV && "Should be SIGSEGV!");
18
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";
23 abort();
24 }
25
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...
29
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");
34
35 // Sanity check to make sure this really is a call instruction...
36 assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!");
37
38 unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RefAddr);
39
40 // Rewrite the call target... so that we don't fault every time we execute
41 // the call.
42 *(unsigned*)RefAddr = NewVal-RefAddr-4;
43
44 // Change the instruction pointer to be the real target of the call...
45 ucp->uc_mcontext.gregs[REG_EIP] = NewVal;
46
47#endif
48}
49
50
51void VM::registerCallback() {
52 TheVM = this;
53
54 // Register the signal handler...
55 struct sigaction SA;
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
60}
61
62