js/src/jscrashreport.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2  * vim: set ts=8 sts=4 et sw=4 tw=99:
     3  * This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "jscrashreport.h"
     9 #include <time.h>
    11 #include "jsapi.h"
    12 #include "jscrashformat.h"
    13 #include "jsutil.h"
    15 using namespace js;
    16 using namespace js::crash;
    18 #if defined(XP_WIN)
    20 static const int stack_snapshot_max_size = 32768;
    22 #include <windows.h>
    24 static bool
    25 GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
    26 {
    27     /* Try to figure out how big the stack is. */
    28     char dummy;
    29     MEMORY_BASIC_INFORMATION info;
    30     if (VirtualQuery(reinterpret_cast<LPCVOID>(&dummy), &info, sizeof(info)) == 0)
    31         return false;
    32     if (info.State != MEM_COMMIT)
    33         return false;
    35     /* 256 is a fudge factor to account for the rest of GetStack's frame. */
    36     uint64_t p = uint64_t(&dummy) - 256;
    37     uint64_t len = stack_snapshot_max_size;
    39     if (p + len > uint64_t(info.BaseAddress) + info.RegionSize)
    40         len = uint64_t(info.BaseAddress) + info.RegionSize - p;
    42     if (len > size)
    43         len = size;
    45     *stack = p;
    46     *stack_len = len;
    48     /* Get the register state. */
    49 #if defined(_MSC_VER) && defined(_M_IX86)
    50     /* ASM version for win2k that doesn't support RtlCaptureContext */
    51     uint32_t vip, vsp, vbp;
    52     __asm {
    53     MyLabel:
    54         mov [vbp], ebp;
    55         mov [vsp], esp;
    56         mov eax, [MyLabel];
    57         mov [vip], eax;
    58     }
    59     regs->ip = vip;
    60     regs->sp = vsp;
    61     regs->bp = vbp;
    62 #else
    63     CONTEXT context;
    64     RtlCaptureContext(&context);
    65 #if defined(_M_IX86)
    66     regs->ip = context.Eip;
    67     regs->sp = context.Esp;
    68     regs->bp = context.Ebp;
    69 #elif defined(_M_X64)
    70     regs->ip = context.Rip;
    71     regs->sp = context.Rsp;
    72     regs->bp = context.Rbp;
    73 #else
    74 #error unknown cpu architecture
    75 #endif
    76 #endif
    78     js_memcpy(buffer, (void *)p, len);
    80     return true;
    81 }
    83 #elif 0
    85 #include <sys/mman.h>
    86 #include <ucontext.h>
    87 #include <unistd.h>
    89 static bool
    90 GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
    91 {
    92     /* 256 is a fudge factor to account for the rest of GetStack's frame. */
    93     char dummy;
    94     uint64_t p = uint64_t(&dummy) - 256;
    95     uint64_t pgsz = getpagesize();
    96     uint64_t len = stack_snapshot_max_size;
    97     p &= ~(pgsz - 1);
    99     /* Try to figure out how big the stack is. */
   100     while (len > 0) {
   101 	if (mlock((const void *)p, len) == 0) {
   102 	    munlock((const void *)p, len);
   103 	    break;
   104 	}
   105 	len -= pgsz;
   106     }
   108     if (len > size)
   109         len = size;
   111     *stack = p;
   112     *stack_len = len;
   114     /* Get the register state. */
   115     ucontext_t context;
   116     if (getcontext(&context) != 0)
   117 	return false;
   119 #if defined(__x86_64__)
   120     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_RSP];
   121     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_RBP];
   122     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_RIP];
   123 #elif defined(__i386__)
   124     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_ESP];
   125     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_EBP];
   126     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_EIP];
   127 #else
   128 #error unknown cpu architecture
   129 #endif
   131     js_memcpy(buffer, (void *)p, len);
   133     return true;
   134 }
   136 #else
   138 static bool
   139 GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
   140 {
   141     return false;
   142 }
   144 #endif
   146 namespace js {
   147 namespace crash {
   149 class Stack : private CrashStack
   150 {
   151 public:
   152     Stack(uint64_t id);
   154     bool snapshot();
   155 };
   157 Stack::Stack(uint64_t id)
   158   : CrashStack(id)
   159 {
   160 }
   162 bool
   163 Stack::snapshot()
   164 {
   165     snaptime = time(nullptr);
   166     return GetStack(&stack_base, &stack_len, &regs, stack, sizeof(stack));
   167 }
   169 class Ring : private CrashRing
   170 {
   171 public:
   172     Ring(uint64_t id);
   174     void push(uint64_t tag, void *data, size_t size);
   176 private:
   177     size_t bufferSize() { return crash_buffer_size; }
   178     void copyBytes(void *data, size_t size);
   179 };
   181 Ring::Ring(uint64_t id)
   182   : CrashRing(id)
   183 {
   184 }
   186 void
   187 Ring::push(uint64_t tag, void *data, size_t size)
   188 {
   189     uint64_t t = time(nullptr);
   191     copyBytes(&tag, sizeof(uint64_t));
   192     copyBytes(&t, sizeof(uint64_t));
   193     copyBytes(data, size);
   194     uint64_t mysize = size;
   195     copyBytes(&mysize, sizeof(uint64_t));
   196 }
   198 void
   199 Ring::copyBytes(void *data, size_t size)
   200 {
   201     if (size >= bufferSize())
   202         size = bufferSize();
   204     if (offset + size > bufferSize()) {
   205         size_t first = bufferSize() - offset;
   206         size_t second = size - first;
   207         js_memcpy(&buffer[offset], data, first);
   208         js_memcpy(buffer, (char *)data + first, second);
   209         offset = second;
   210     } else {
   211         js_memcpy(&buffer[offset], data, size);
   212         offset += size;
   213     }
   214 }
   216 } /* namespace crash */
   217 } /* namespace js */
   219 #ifdef JS_CRASH_DIAGNOSTICS
   220 static bool gInitialized;
   222 static Stack gGCStack(JS_CRASH_STACK_GC);
   223 static Stack gErrorStack(JS_CRASH_STACK_ERROR);
   224 static Ring gRingBuffer(JS_CRASH_RING);
   225 #endif
   227 void
   228 js::crash::SnapshotGCStack()
   229 {
   230 #ifdef JS_CRASH_DIAGNOSTICS
   231     if (gInitialized)
   232         gGCStack.snapshot();
   233 #endif
   234 }
   236 void
   237 js::crash::SnapshotErrorStack()
   238 {
   239 #ifdef JS_CRASH_DIAGNOSTICS
   240     if (gInitialized)
   241         gErrorStack.snapshot();
   242 #endif
   243 }
   245 void
   246 js::crash::SaveCrashData(uint64_t tag, void *ptr, size_t size)
   247 {
   248 #ifdef JS_CRASH_DIAGNOSTICS
   249     if (gInitialized)
   250         gRingBuffer.push(tag, ptr, size);
   251 #endif
   252 }
   254 JS_PUBLIC_API(void)
   255 JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback)
   256 {
   257 #ifdef JS_CRASH_DIAGNOSTICS
   258     if (!gInitialized) {
   259         gInitialized = true;
   260         (*callback)(&gGCStack, sizeof(gGCStack));
   261         (*callback)(&gErrorStack, sizeof(gErrorStack));
   262         (*callback)(&gRingBuffer, sizeof(gRingBuffer));
   263     }
   264 #endif
   265 }

mercurial