Initial checkin of Unresolved function fault handler
authorChris Lattner <sabre@nondot.org>
Wed, 4 Dec 2002 05:05:26 +0000 (05:05 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 4 Dec 2002 05:05:26 +0000 (05:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4900 91177308-0d34-0410-b5e6-96231b3b80d8

tools/jello/Callback.cpp [new file with mode: 0644]

diff --git a/tools/jello/Callback.cpp b/tools/jello/Callback.cpp
new file mode 100644 (file)
index 0000000..173657d
--- /dev/null
@@ -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
+}
+
+