LCOV - app.info - js/src/jscrashreport.cpp

LCOV - code coverage report
| Current view: | directory - js/src - jscrashreport.cpp (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 54 | 13 | 24.1 %
| Date: | 2012-04-07 | Functions: | 14 | 5 | 35.7 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
           2                 :  * vim: set ts=4 sw=4 et tw=99:
           3                 :  *
           4                 :  * ***** BEGIN LICENSE BLOCK *****
           5                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           6                 :  *
           7                 :  * The contents of this file are subject to the Mozilla Public License Version
           8                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           9                 :  * the License. You may obtain a copy of the License at
          10                 :  * http://www.mozilla.org/MPL/
          11                 :  *
          12                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          13                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          14                 :  * for the specific language governing rights and limitations under the
          15                 :  * License.
          16                 :  *
          17                 :  * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released
          18                 :  * May 28, 2008.
          19                 :  *
          20                 :  * The Initial Developer of the Original Code is
          21                 :  *   Mozilla Foundation
          22                 :  * Portions created by the Initial Developer are Copyright (C) 2011
          23                 :  * the Initial Developer. All Rights Reserved.
          24                 :  *
          25                 :  * Contributor(s):
          26                 :  *
          27                 :  * Alternatively, the contents of this file may be used under the terms of
          28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
          29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          31                 :  * of those above. If you wish to allow use of your version of this file only
          32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          33                 :  * use your version of this file under the terms of the MPL, indicate your
          34                 :  * decision by deleting the provisions above and replace them with the notice
          35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          36                 :  * the provisions above, a recipient may use your version of this file under
          37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          38                 :  *
          39                 :  * ***** END LICENSE BLOCK ***** */
          40                 :
          41                 : #include "jsapi.h"
          42                 : #include "jscntxt.h"
          43                 : #include "jscrashreport.h"
          44                 : #include "jscrashformat.h"
          45                 :
          46                 : #include <time.h>
          47                 :
          48                 : namespace js {
          49                 : namespace crash {
          50                 :
          51                 : const static int stack_snapshot_max_size = 32768;
          52                 :
          53                 : #if defined(XP_WIN)
          54                 :
          55                 : #include <windows.h>
          56                 :
          57                 : static bool
          58                 : GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
          59                 : {
          60                 :     /* Try to figure out how big the stack is. */
          61                 :     char dummy;
          62                 :     MEMORY_BASIC_INFORMATION info;
          63                 :     if (VirtualQuery(reinterpret_cast<LPCVOID>(&dummy), &info, sizeof(info)) == 0)
          64                 :         return false;
          65                 :     if (info.State != MEM_COMMIT)
          66                 :         return false;
          67                 :
          68                 :     /* 256 is a fudge factor to account for the rest of GetStack's frame. */
          69                 :     uint64_t p = uint64_t(&dummy) - 256;
          70                 :     uint64_t len = stack_snapshot_max_size;
          71                 :
          72                 :     if (p + len > uint64_t(info.BaseAddress) + info.RegionSize)
          73                 :         len = uint64_t(info.BaseAddress) + info.RegionSize - p;
          74                 :
          75                 :     if (len > size)
          76                 :         len = size;
          77                 :
          78                 :     *stack = p;
          79                 :     *stack_len = len;
          80                 :
          81                 :     /* Get the register state. */
          82                 : #if defined(_MSC_VER) && JS_BITS_PER_WORD == 32
          83                 :     /* ASM version for win2k that doesn't support RtlCaptureContext */
          84                 :     uint32_t vip, vsp, vbp;
          85                 :     __asm {
          86                 :     Label:
          87                 :         mov [vbp], ebp;
          88                 :         mov [vsp], esp;
          89                 :         mov eax, [Label];
          90                 :         mov [vip], eax;
          91                 :     }
          92                 :     regs->ip = vip;
          93                 :     regs->sp = vsp;
          94                 :     regs->bp = vbp;
          95                 : #else
          96                 :     CONTEXT context;
          97                 :     RtlCaptureContext(&context);
          98                 : #if JS_BITS_PER_WORD == 32
          99                 :     regs->ip = context.Eip;
         100                 :     regs->sp = context.Esp;
         101                 :     regs->bp = context.Ebp;
         102                 : #else
         103                 :     regs->ip = context.Rip;
         104                 :     regs->sp = context.Rsp;
         105                 :     regs->bp = context.Rbp;
         106                 : #endif
         107                 : #endif
         108                 :
         109                 :     js_memcpy(buffer, (void *)p, len);
         110                 :
         111                 :     return true;
         112                 : }
         113                 :
         114                 : #elif 0
         115                 :
         116                 : #include <unistd.h>
         117                 : #include <ucontext.h>
         118                 : #include <sys/mman.h>
         119                 :
         120                 : static bool
         121                 : GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
         122                 : {
         123                 :     /* 256 is a fudge factor to account for the rest of GetStack's frame. */
         124                 :     char dummy;
         125                 :     uint64_t p = uint64_t(&dummy) - 256;
         126                 :     uint64_t pgsz = getpagesize();
         127                 :     uint64_t len = stack_snapshot_max_size;
         128                 :     p &= ~(pgsz - 1);
         129                 :
         130                 :     /* Try to figure out how big the stack is. */
         131                 :     while (len > 0) {
         132                 :         if (mlock((const void *)p, len) == 0) {
         133                 :             munlock((const void *)p, len);
         134                 :             break;
         135                 :         }
         136                 :         len -= pgsz;
         137                 :     }
         138                 :
         139                 :     if (len > size)
         140                 :         len = size;
         141                 :
         142                 :     *stack = p;
         143                 :     *stack_len = len;
         144                 :
         145                 :     /* Get the register state. */
         146                 :     ucontext_t context;
         147                 :     if (getcontext(&context) != 0)
         148                 :         return false;
         149                 :
         150                 : #if JS_BITS_PER_WORD == 64
         151                 :     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_RSP];
         152                 :     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_RBP];
         153                 :     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_RIP];
         154                 : #elif JS_BITS_PER_WORD == 32
         155                 :     regs->sp = (uint64_t)context.uc_mcontext.gregs[REG_ESP];
         156                 :     regs->bp = (uint64_t)context.uc_mcontext.gregs[REG_EBP];
         157                 :     regs->ip = (uint64_t)context.uc_mcontext.gregs[REG_EIP];
         158                 : #endif
         159                 :
         160                 :     js_memcpy(buffer, (void *)p, len);
         161                 :
         162                 :     return true;
         163                 : }
         164                 :
         165                 : #else
         166                 :
         167                 : static bool
         168               0 : GetStack(uint64_t *stack, uint64_t *stack_len, CrashRegisters *regs, char *buffer, size_t size)
         169                 : {
         170               0 :     return false;
         171                 : }
         172                 :
         173                 : #endif
         174                 :
         175                 : class Stack : private CrashStack
         176                 : {
         177                 : public:
         178                 :     Stack(uint64_t id);
         179                 :
         180                 :     bool snapshot();
         181                 : };
         182                 :
         183           37334 : Stack::Stack(uint64_t id)
         184           37334 :   : CrashStack(id)
         185                 : {
         186           37334 : }
         187                 :
         188                 : bool
         189               0 : Stack::snapshot()
         190                 : {
         191               0 :     snaptime = time(NULL);
         192               0 :     return GetStack(&stack_base, &stack_len, &regs, stack, sizeof(stack));
         193                 : }
         194                 :
         195                 : class Ring : private CrashRing
         196                 : {
         197                 : public:
         198                 :     Ring(uint64_t id);
         199                 :
         200                 :     void push(uint64_t tag, void *data, size_t size);
         201                 :
         202                 : private:
         203               0 :     size_t bufferSize() { return crash_buffer_size; }
         204                 :     void copyBytes(void *data, size_t size);
         205                 : };
         206                 :
         207           18667 : Ring::Ring(uint64_t id)
         208           18667 :   : CrashRing(id)
         209                 : {
         210           18667 : }
         211                 :
         212                 : void
         213               0 : Ring::push(uint64_t tag, void *data, size_t size)
         214                 : {
         215               0 :     uint64_t t = time(NULL);
         216                 :
         217               0 :     copyBytes(&tag, sizeof(uint64_t));
         218               0 :     copyBytes(&t, sizeof(uint64_t));
         219               0 :     copyBytes(data, size);
         220               0 :     uint64_t mysize = size;
         221               0 :     copyBytes(&mysize, sizeof(uint64_t));
         222               0 : }
         223                 :
         224                 : void
         225               0 : Ring::copyBytes(void *data, size_t size)
         226                 : {
         227               0 :     if (size >= bufferSize())
         228               0 :         size = bufferSize();
         229                 :
         230               0 :     if (offset + size > bufferSize()) {
         231               0 :         size_t first = bufferSize() - offset;
         232               0 :         size_t second = size - first;
         233               0 :         js_memcpy(&buffer[offset], data, first);
         234               0 :         js_memcpy(buffer, (char *)data + first, second);
         235               0 :         offset = second;
         236                 :     } else {
         237               0 :         js_memcpy(&buffer[offset], data, size);
         238               0 :         offset += size;
         239                 :     }
         240               0 : }
         241                 :
         242                 : static bool gInitialized;
         243                 :
         244           18667 : static Stack gGCStack(JS_CRASH_STACK_GC);
         245           18667 : static Stack gErrorStack(JS_CRASH_STACK_ERROR);
         246           18667 : static Ring gRingBuffer(JS_CRASH_RING);
         247                 :
         248                 : void
         249           38427 : SnapshotGCStack()
         250                 : {
         251           38427 :     if (gInitialized)
         252               0 :         gGCStack.snapshot();
         253           38427 : }
         254                 :
         255                 : void
         256               0 : SnapshotErrorStack()
         257                 : {
         258               0 :     if (gInitialized)
         259               0 :         gErrorStack.snapshot();
         260               0 : }
         261                 :
         262                 : void
         263               0 : SaveCrashData(uint64_t tag, void *ptr, size_t size)
         264                 : {
         265               0 :     if (gInitialized)
         266               0 :         gRingBuffer.push(tag, ptr, size);
         267               0 : }
         268                 :
         269                 : } /* namespace crash */
         270                 : } /* namespace js */
         271                 :
         272                 : using namespace js;
         273                 : using namespace js::crash;
         274                 :
         275                 : JS_PUBLIC_API(void)
         276               0 : JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback)
         277                 : {
         278                 : #ifdef JS_CRASH_DIAGNOSTICS
         279               0 :     if (!gInitialized) {
         280               0 :         gInitialized = true;
         281               0 :         (*callback)(&gGCStack, sizeof(gGCStack));
         282               0 :         (*callback)(&gErrorStack, sizeof(gErrorStack));
         283               0 :         (*callback)(&gRingBuffer, sizeof(gRingBuffer));
         284                 :     }
         285                 : #endif
         286           56001 : }
         287                 :

Generated by: LCOV version 1.7