| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <signal.h> |
| 6 #include <ucontext.h> |
| 7 |
| 5 #include "src/v8.h" | 8 #include "src/v8.h" |
| 6 | 9 |
| 7 #include "src/assembler.h" | 10 #include "src/assembler.h" |
| 8 #include "src/base/once.h" | 11 #include "src/base/once.h" |
| 9 #include "src/base/platform/platform.h" | 12 #include "src/base/platform/platform.h" |
| 10 #include "src/bootstrapper.h" | 13 #include "src/bootstrapper.h" |
| 11 #include "src/compiler/pipeline.h" | 14 #include "src/compiler/pipeline.h" |
| 12 #include "src/debug.h" | 15 #include "src/debug.h" |
| 13 #include "src/deoptimizer.h" | 16 #include "src/deoptimizer.h" |
| 14 #include "src/elements.h" | 17 #include "src/elements.h" |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 FlagList::ResetAllFlags(); // Frees memory held by string arguments. | 61 FlagList::ResetAllFlags(); // Frees memory held by string arguments. |
| 59 } | 62 } |
| 60 | 63 |
| 61 | 64 |
| 62 void V8::SetReturnAddressLocationResolver( | 65 void V8::SetReturnAddressLocationResolver( |
| 63 ReturnAddressLocationResolver resolver) { | 66 ReturnAddressLocationResolver resolver) { |
| 64 StackFrame::SetReturnAddressLocationResolver(resolver); | 67 StackFrame::SetReturnAddressLocationResolver(resolver); |
| 65 } | 68 } |
| 66 | 69 |
| 67 | 70 |
| 71 // TODO(bmeurer): Move to signal-handlers.cc? |
| 72 namespace { |
| 73 |
| 74 struct sigaction prev_handler; |
| 75 |
| 76 |
| 77 struct Decoder { |
| 78 void get_modrm(uint8_t data, int* mod, int* regop, int* rm) { |
| 79 *mod = (data >> 6) & 3; |
| 80 *regop = (data & 0x38) >> 3; |
| 81 *rm = (data & 7); |
| 82 } |
| 83 |
| 84 void get_sib(uint8_t data, int* scale, int* index, int* base) { |
| 85 *scale = (data >> 6) & 3; |
| 86 *index = ((data >> 3) & 7); |
| 87 *base = (data & 7); |
| 88 } |
| 89 |
| 90 int right_operand(uint8_t* modrmp) { |
| 91 int mod, regop, rm; |
| 92 get_modrm(*modrmp, &mod, ®op, &rm); |
| 93 switch (mod) { |
| 94 case 0: |
| 95 if (rm == 5) { |
| 96 return 5; |
| 97 } else if (rm == 4) { |
| 98 int scale, index, base; |
| 99 get_sib(modrmp[1], &scale, &index, &base); |
| 100 return base == 5 ? 6 : 2; |
| 101 } else { |
| 102 return 1; |
| 103 } |
| 104 case 1: |
| 105 return 2 + (rm == 4); |
| 106 case 2: |
| 107 return 5 + (rm == 4); |
| 108 case 3: |
| 109 return 1; |
| 110 default: |
| 111 break; |
| 112 } |
| 113 UNREACHABLE(); |
| 114 return 0; |
| 115 } |
| 116 |
| 117 bool Decode(uint8_t** ppc) { |
| 118 uint8_t* pc = *ppc; |
| 119 bool operand_word_size = false; |
| 120 while (true) { |
| 121 if (*pc == 0x66) { // Group 3 prefix. |
| 122 operand_word_size = true; |
| 123 } else if ((*pc & 0xF0) == 0x40) { |
| 124 // Skip REX. |
| 125 } else { |
| 126 break; // Not a prefix - an opcode. |
| 127 } |
| 128 ++pc; |
| 129 } |
| 130 switch (*pc) { |
| 131 case 0x0F: { |
| 132 if (pc[1] == 0xB6) { // mov |
| 133 } |
| 134 break; |
| 135 } |
| 136 case 0xF2: { |
| 137 if (pc[1] == 0x0F && pc[2] == 0x11) { // movsd mem,reg |
| 138 pc += 3; |
| 139 *ppc = pc + right_operand(pc); |
| 140 PrintF("*** movsd mem,reg\n"); |
| 141 return true; |
| 142 } |
| 143 break; |
| 144 } |
| 145 case 0xF3: { |
| 146 if (pc[1] == 0x0F && pc[2] == 0x11) { // movss mem,reg |
| 147 pc += 3; |
| 148 *ppc = pc + right_operand(pc); |
| 149 PrintF("*** movss mem,reg\n"); |
| 150 return true; |
| 151 } |
| 152 break; |
| 153 } |
| 154 case 0x88: |
| 155 case 0x89: { // mov mem,reg |
| 156 ++pc; |
| 157 *ppc = pc + right_operand(pc); |
| 158 PrintF("*** mov mem,reg\n"); |
| 159 return true; |
| 160 } |
| 161 case 0xC6: { // mov mem,imm8 |
| 162 ++pc; |
| 163 *ppc = pc + right_operand(pc) + 1; |
| 164 PrintF("*** mov mem,imm8\n"); |
| 165 return true; |
| 166 } |
| 167 case 0xC7: { |
| 168 ++pc; |
| 169 if (operand_word_size) { // mov mem,imm16 |
| 170 *ppc = pc + right_operand(pc) + 2; |
| 171 PrintF("*** mov mem,imm16\n"); |
| 172 } else { // mov mem,imm32 |
| 173 *ppc = pc + right_operand(pc) + 4; |
| 174 PrintF("*** mov mem,imm32\n"); |
| 175 } |
| 176 return true; |
| 177 } |
| 178 default: |
| 179 break; |
| 180 } |
| 181 return false; |
| 182 } |
| 183 }; |
| 184 |
| 185 |
| 186 bool DecodeHeapAccess(uint8_t** ppc) { |
| 187 Decoder decoder; |
| 188 return decoder.Decode(ppc); |
| 189 } |
| 190 |
| 191 |
| 192 bool HandleFault(int signum, siginfo_t* si, ucontext_t* uc) { |
| 193 if (signum != SIGSEGV) return false; |
| 194 Isolate* const isolate = Isolate::UnsafeCurrent(); |
| 195 if (!isolate || !isolate->IsInUse()) { |
| 196 // We require a fully initialized and entered isolate. |
| 197 return false; |
| 198 } |
| 199 if (v8::Locker::IsActive() && |
| 200 !isolate->thread_manager()->IsLockedByCurrentThread()) { |
| 201 return false; |
| 202 } |
| 203 if (!isolate->IsInGuardArea(si->si_addr)) return false; |
| 204 uint8_t** ppc = reinterpret_cast<uint8_t**>(&uc->uc_mcontext.gregs[REG_RIP]); |
| 205 if (DecodeHeapAccess(ppc)) return true; |
| 206 PrintF("*** Unhandled fault at %p!\n", *ppc); |
| 207 return false; |
| 208 } |
| 209 |
| 210 |
| 211 void FaultHandler(int signum, siginfo_t* si, void* context) { |
| 212 if (HandleFault(signum, si, static_cast<ucontext_t*>(context))) return; |
| 213 |
| 214 // This signal is not for any asm.js code we expect, so we need to forward |
| 215 // the signal to the next handler. If there is no next handler (SIG_IGN or |
| 216 // SIG_DFL), then it's time to crash. To do this, we set the signal back to |
| 217 // its original disposition and return. This will cause the faulting op to |
| 218 // be re-executed which will crash in the normal way. The advantage of |
| 219 // doing this to calling _exit() is that we remove ourselves from the crash |
| 220 // stack which improves crash reports. If there is a next handler, call it. |
| 221 // It will either crash synchronously, fix up the instruction so that |
| 222 // execution can continue and return, or trigger a crash by returning the |
| 223 // signal to it's original disposition and returning. |
| 224 // |
| 225 // Note: the order of these tests matter. |
| 226 if (prev_handler.sa_flags & SA_SIGINFO) { |
| 227 prev_handler.sa_sigaction(signum, si, context); |
| 228 } else if (prev_handler.sa_handler == SIG_DFL || |
| 229 prev_handler.sa_handler == SIG_IGN) { |
| 230 sigaction(signum, &prev_handler, nullptr); |
| 231 } else { |
| 232 prev_handler.sa_handler(signum); |
| 233 } |
| 234 } |
| 235 |
| 236 |
| 237 void InstallFaultHandler() { |
| 238 // SA_NODEFER allows us to reenter the signal handler if we crash while |
| 239 // handling the signal. |
| 240 struct sigaction sa; |
| 241 bzero(&sa, sizeof(sa)); |
| 242 sa.sa_flags = SA_SIGINFO | SA_NODEFER; |
| 243 sa.sa_sigaction = &FaultHandler; |
| 244 sigemptyset(&sa.sa_mask); |
| 245 sigaction(SIGSEGV, &sa, &prev_handler); |
| 246 } |
| 247 |
| 248 } // namespace |
| 249 |
| 250 |
| 68 void V8::InitializeOncePerProcessImpl() { | 251 void V8::InitializeOncePerProcessImpl() { |
| 69 FlagList::EnforceFlagImplications(); | 252 FlagList::EnforceFlagImplications(); |
| 70 | 253 |
| 71 if (FLAG_predictable && FLAG_random_seed == 0) { | 254 if (FLAG_predictable && FLAG_random_seed == 0) { |
| 72 // Avoid random seeds in predictable mode. | 255 // Avoid random seeds in predictable mode. |
| 73 FLAG_random_seed = 12347; | 256 FLAG_random_seed = 12347; |
| 74 } | 257 } |
| 75 | 258 |
| 76 if (FLAG_stress_compaction) { | 259 if (FLAG_stress_compaction) { |
| 77 FLAG_force_marking_deque_overflows = true; | 260 FLAG_force_marking_deque_overflows = true; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 91 init_fast_sqrt_function(); | 274 init_fast_sqrt_function(); |
| 92 #ifdef _WIN64 | 275 #ifdef _WIN64 |
| 93 init_modulo_function(); | 276 init_modulo_function(); |
| 94 #endif | 277 #endif |
| 95 ElementsAccessor::InitializeOncePerProcess(); | 278 ElementsAccessor::InitializeOncePerProcess(); |
| 96 LOperand::SetUpCaches(); | 279 LOperand::SetUpCaches(); |
| 97 compiler::Pipeline::SetUp(); | 280 compiler::Pipeline::SetUp(); |
| 98 SetUpJSCallerSavedCodeData(); | 281 SetUpJSCallerSavedCodeData(); |
| 99 ExternalReference::SetUp(); | 282 ExternalReference::SetUp(); |
| 100 Bootstrapper::InitializeOncePerProcess(); | 283 Bootstrapper::InitializeOncePerProcess(); |
| 284 InstallFaultHandler(); |
| 101 } | 285 } |
| 102 | 286 |
| 103 | 287 |
| 104 void V8::InitializeOncePerProcess() { | 288 void V8::InitializeOncePerProcess() { |
| 105 base::CallOnce(&init_once, &InitializeOncePerProcessImpl); | 289 base::CallOnce(&init_once, &InitializeOncePerProcessImpl); |
| 106 } | 290 } |
| 107 | 291 |
| 108 | 292 |
| 109 void V8::InitializePlatform(v8::Platform* platform) { | 293 void V8::InitializePlatform(v8::Platform* platform) { |
| 110 CHECK(!platform_); | 294 CHECK(!platform_); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 135 | 319 |
| 136 | 320 |
| 137 void V8::SetSnapshotBlob(StartupData* snapshot_blob) { | 321 void V8::SetSnapshotBlob(StartupData* snapshot_blob) { |
| 138 #ifdef V8_USE_EXTERNAL_STARTUP_DATA | 322 #ifdef V8_USE_EXTERNAL_STARTUP_DATA |
| 139 base::CallOnce(&init_snapshot_once, &SetSnapshotFromFile, snapshot_blob); | 323 base::CallOnce(&init_snapshot_once, &SetSnapshotFromFile, snapshot_blob); |
| 140 #else | 324 #else |
| 141 CHECK(false); | 325 CHECK(false); |
| 142 #endif | 326 #endif |
| 143 } | 327 } |
| 144 } } // namespace v8::internal | 328 } } // namespace v8::internal |
| OLD | NEW |