Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(611)

Unified Diff: src/v8.cc

Issue 768543002: [WIP] TrapHandler 2014/11/27. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime/runtime-typedarray.cc ('k') | test/cctest/cctest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/v8.cc
diff --git a/src/v8.cc b/src/v8.cc
index b04ccc07c700e35f572bc42f4eec949315174766..e8af10546db8bc605a31a1cdb6e55d534538aae4 100644
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <signal.h>
+#include <ucontext.h>
+
#include "src/v8.h"
#include "src/assembler.h"
@@ -65,6 +68,186 @@ void V8::SetReturnAddressLocationResolver(
}
+// TODO(bmeurer): Move to signal-handlers.cc?
+namespace {
+
+struct sigaction prev_handler;
+
+
+struct Decoder {
+ void get_modrm(uint8_t data, int* mod, int* regop, int* rm) {
+ *mod = (data >> 6) & 3;
+ *regop = (data & 0x38) >> 3;
+ *rm = (data & 7);
+ }
+
+ void get_sib(uint8_t data, int* scale, int* index, int* base) {
+ *scale = (data >> 6) & 3;
+ *index = ((data >> 3) & 7);
+ *base = (data & 7);
+ }
+
+ int right_operand(uint8_t* modrmp) {
+ int mod, regop, rm;
+ get_modrm(*modrmp, &mod, &regop, &rm);
+ switch (mod) {
+ case 0:
+ if (rm == 5) {
+ return 5;
+ } else if (rm == 4) {
+ int scale, index, base;
+ get_sib(modrmp[1], &scale, &index, &base);
+ return base == 5 ? 6 : 2;
+ } else {
+ return 1;
+ }
+ case 1:
+ return 2 + (rm == 4);
+ case 2:
+ return 5 + (rm == 4);
+ case 3:
+ return 1;
+ default:
+ break;
+ }
+ UNREACHABLE();
+ return 0;
+ }
+
+ bool Decode(uint8_t** ppc) {
+ uint8_t* pc = *ppc;
+ bool operand_word_size = false;
+ while (true) {
+ if (*pc == 0x66) { // Group 3 prefix.
+ operand_word_size = true;
+ } else if ((*pc & 0xF0) == 0x40) {
+ // Skip REX.
+ } else {
+ break; // Not a prefix - an opcode.
+ }
+ ++pc;
+ }
+ switch (*pc) {
+ case 0x0F: {
+ if (pc[1] == 0xB6) { // mov
+ }
+ break;
+ }
+ case 0xF2: {
+ if (pc[1] == 0x0F && pc[2] == 0x11) { // movsd mem,reg
+ pc += 3;
+ *ppc = pc + right_operand(pc);
+ PrintF("*** movsd mem,reg\n");
+ return true;
+ }
+ break;
+ }
+ case 0xF3: {
+ if (pc[1] == 0x0F && pc[2] == 0x11) { // movss mem,reg
+ pc += 3;
+ *ppc = pc + right_operand(pc);
+ PrintF("*** movss mem,reg\n");
+ return true;
+ }
+ break;
+ }
+ case 0x88:
+ case 0x89: { // mov mem,reg
+ ++pc;
+ *ppc = pc + right_operand(pc);
+ PrintF("*** mov mem,reg\n");
+ return true;
+ }
+ case 0xC6: { // mov mem,imm8
+ ++pc;
+ *ppc = pc + right_operand(pc) + 1;
+ PrintF("*** mov mem,imm8\n");
+ return true;
+ }
+ case 0xC7: {
+ ++pc;
+ if (operand_word_size) { // mov mem,imm16
+ *ppc = pc + right_operand(pc) + 2;
+ PrintF("*** mov mem,imm16\n");
+ } else { // mov mem,imm32
+ *ppc = pc + right_operand(pc) + 4;
+ PrintF("*** mov mem,imm32\n");
+ }
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+ }
+};
+
+
+bool DecodeHeapAccess(uint8_t** ppc) {
+ Decoder decoder;
+ return decoder.Decode(ppc);
+}
+
+
+bool HandleFault(int signum, siginfo_t* si, ucontext_t* uc) {
+ if (signum != SIGSEGV) return false;
+ Isolate* const isolate = Isolate::UnsafeCurrent();
+ if (!isolate || !isolate->IsInUse()) {
+ // We require a fully initialized and entered isolate.
+ return false;
+ }
+ if (v8::Locker::IsActive() &&
+ !isolate->thread_manager()->IsLockedByCurrentThread()) {
+ return false;
+ }
+ if (!isolate->IsInGuardArea(si->si_addr)) return false;
+ uint8_t** ppc = reinterpret_cast<uint8_t**>(&uc->uc_mcontext.gregs[REG_RIP]);
+ if (DecodeHeapAccess(ppc)) return true;
+ PrintF("*** Unhandled fault at %p!\n", *ppc);
+ return false;
+}
+
+
+void FaultHandler(int signum, siginfo_t* si, void* context) {
+ if (HandleFault(signum, si, static_cast<ucontext_t*>(context))) return;
+
+ // This signal is not for any asm.js code we expect, so we need to forward
+ // the signal to the next handler. If there is no next handler (SIG_IGN or
+ // SIG_DFL), then it's time to crash. To do this, we set the signal back to
+ // its original disposition and return. This will cause the faulting op to
+ // be re-executed which will crash in the normal way. The advantage of
+ // doing this to calling _exit() is that we remove ourselves from the crash
+ // stack which improves crash reports. If there is a next handler, call it.
+ // It will either crash synchronously, fix up the instruction so that
+ // execution can continue and return, or trigger a crash by returning the
+ // signal to it's original disposition and returning.
+ //
+ // Note: the order of these tests matter.
+ if (prev_handler.sa_flags & SA_SIGINFO) {
+ prev_handler.sa_sigaction(signum, si, context);
+ } else if (prev_handler.sa_handler == SIG_DFL ||
+ prev_handler.sa_handler == SIG_IGN) {
+ sigaction(signum, &prev_handler, nullptr);
+ } else {
+ prev_handler.sa_handler(signum);
+ }
+}
+
+
+void InstallFaultHandler() {
+ // SA_NODEFER allows us to reenter the signal handler if we crash while
+ // handling the signal.
+ struct sigaction sa;
+ bzero(&sa, sizeof(sa));
+ sa.sa_flags = SA_SIGINFO | SA_NODEFER;
+ sa.sa_sigaction = &FaultHandler;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGSEGV, &sa, &prev_handler);
+}
+
+} // namespace
+
+
void V8::InitializeOncePerProcessImpl() {
FlagList::EnforceFlagImplications();
@@ -98,6 +281,7 @@ void V8::InitializeOncePerProcessImpl() {
SetUpJSCallerSavedCodeData();
ExternalReference::SetUp();
Bootstrapper::InitializeOncePerProcess();
+ InstallFaultHandler();
}
« no previous file with comments | « src/runtime/runtime-typedarray.cc ('k') | test/cctest/cctest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698