mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-21 01:25:20 +00:00
Initial checkin of Unresolved function fault handler
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4900 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d6c10ea817
commit
41db76dec2
58
tools/jello/Callback.cpp
Normal file
58
tools/jello/Callback.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
//===-- 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 <signal.h>
|
||||||
|
#include <ucontext.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
static VM *TheVM = 0;
|
||||||
|
|
||||||
|
static void TrapHandler(int TN, siginfo_t *SI, ucontext_t *ucp) {
|
||||||
|
assert(TN == SIGSEGV && "Should be SIGSEGV!");
|
||||||
|
|
||||||
|
if (SI->si_code != SEGV_MAPERR || SI->si_addr != 0 ||
|
||||||
|
ucp->uc_mcontext.gregs[REG_EIP] != 0) {
|
||||||
|
std::cerr << "Bad SEGV encountered!\n";
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
// The call instruction should have pushed the return value onto the stack...
|
||||||
|
unsigned RefAddr = *(unsigned*)ucp->uc_mcontext.gregs[REG_ESP];
|
||||||
|
RefAddr -= 4; // Backtrack to the reference itself...
|
||||||
|
|
||||||
|
std::cerr << "In SEGV handler! Addr=0x" << std::hex << RefAddr
|
||||||
|
<< " ESP=0x" << ucp->uc_mcontext.gregs[REG_ESP] << std::dec
|
||||||
|
<< ": Resolving call to function: "
|
||||||
|
<< TheVM->getFunctionReferencedName((void*)RefAddr) << "\n";
|
||||||
|
|
||||||
|
// Sanity check to make sure this really is a call instruction...
|
||||||
|
assert(((unsigned char*)RefAddr)[-1] == 0xE8 && "Not a call instr!");
|
||||||
|
|
||||||
|
unsigned NewVal = (unsigned)TheVM->resolveFunctionReference((void*)RefAddr);
|
||||||
|
|
||||||
|
// Rewrite the call target... so that we don't fault every time we execute
|
||||||
|
// the call.
|
||||||
|
*(unsigned*)RefAddr = NewVal-RefAddr-4;
|
||||||
|
|
||||||
|
// Change the instruction pointer to be the real target of the call...
|
||||||
|
ucp->uc_mcontext.gregs[REG_EIP] = NewVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VM::registerCallback() {
|
||||||
|
TheVM = this;
|
||||||
|
|
||||||
|
// Register the signal handler...
|
||||||
|
struct sigaction SA;
|
||||||
|
SA.sa_sigaction = (void (*)(int, siginfo_t*, void*))TrapHandler;
|
||||||
|
sigfillset(&SA.sa_mask); // Block all signals while codegen'ing
|
||||||
|
SA.sa_flags = SA_NOCLDSTOP|SA_SIGINFO; // Get siginfo
|
||||||
|
sigaction(SIGSEGV, &SA, 0); // Install the handler
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user