| Index: tools/oom_dump/oom_dump.cc
|
| diff --git a/tools/oom_dump/oom_dump.cc b/tools/oom_dump/oom_dump.cc
|
| deleted file mode 100644
|
| index 581e1914e2e345497c9a4a2a47f319a10e7ae07b..0000000000000000000000000000000000000000
|
| --- a/tools/oom_dump/oom_dump.cc
|
| +++ /dev/null
|
| @@ -1,283 +0,0 @@
|
| -// Copyright 2010 the V8 project authors. All rights reserved.
|
| -// Redistribution and use in source and binary forms, with or without
|
| -// modification, are permitted provided that the following conditions are
|
| -// met:
|
| -//
|
| -// * Redistributions of source code must retain the above copyright
|
| -// notice, this list of conditions and the following disclaimer.
|
| -// * Redistributions in binary form must reproduce the above
|
| -// copyright notice, this list of conditions and the following
|
| -// disclaimer in the documentation and/or other materials provided
|
| -// with the distribution.
|
| -// * Neither the name of Google Inc. nor the names of its
|
| -// contributors may be used to endorse or promote products derived
|
| -// from this software without specific prior written permission.
|
| -//
|
| -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| -
|
| -#include <stdio.h>
|
| -#include <stdlib.h>
|
| -
|
| -#include <algorithm>
|
| -
|
| -#include <google_breakpad/processor/minidump.h>
|
| -
|
| -#include <v8.h>
|
| -
|
| -namespace {
|
| -
|
| -using google_breakpad::Minidump;
|
| -using google_breakpad::MinidumpContext;
|
| -using google_breakpad::MinidumpThread;
|
| -using google_breakpad::MinidumpThreadList;
|
| -using google_breakpad::MinidumpException;
|
| -using google_breakpad::MinidumpMemoryRegion;
|
| -
|
| -const char* InstanceTypeToString(int type) {
|
| - static char const* names[v8::internal::LAST_TYPE] = {0};
|
| - if (names[v8::internal::STRING_TYPE] == NULL) {
|
| - using namespace v8::internal;
|
| -#define SET(type) names[type] = #type;
|
| - INSTANCE_TYPE_LIST(SET)
|
| -#undef SET
|
| - }
|
| - return names[type];
|
| -}
|
| -
|
| -
|
| -u_int32_t ReadPointedValue(MinidumpMemoryRegion* region,
|
| - u_int64_t base,
|
| - int offset) {
|
| - u_int32_t ptr = 0;
|
| - CHECK(region->GetMemoryAtAddress(base + 4 * offset, &ptr));
|
| - u_int32_t value = 0;
|
| - CHECK(region->GetMemoryAtAddress(ptr, &value));
|
| - return value;
|
| -}
|
| -
|
| -
|
| -void ReadArray(MinidumpMemoryRegion* region,
|
| - u_int64_t array_ptr,
|
| - int size,
|
| - int* output) {
|
| - for (int i = 0; i < size; i++) {
|
| - u_int32_t value;
|
| - CHECK(region->GetMemoryAtAddress(array_ptr + 4 * i, &value));
|
| - output[i] = value;
|
| - }
|
| -}
|
| -
|
| -
|
| -u_int32_t ReadArrayFrom(MinidumpMemoryRegion* region,
|
| - u_int64_t base,
|
| - int offset,
|
| - int size,
|
| - int* output) {
|
| - u_int32_t ptr = 0;
|
| - CHECK(region->GetMemoryAtAddress(base + 4 * offset, &ptr));
|
| - ReadArray(region, ptr, size, output);
|
| -}
|
| -
|
| -
|
| -double toM(int size) {
|
| - return size / (1024. * 1024.);
|
| -}
|
| -
|
| -
|
| -class IndirectSorter {
|
| - public:
|
| - explicit IndirectSorter(int* a) : a_(a) { }
|
| -
|
| - bool operator() (int i0, int i1) {
|
| - return a_[i0] > a_[i1];
|
| - }
|
| -
|
| - private:
|
| - int* a_;
|
| -};
|
| -
|
| -
|
| -void DumpHeapStats(const char *minidump_file) {
|
| - Minidump minidump(minidump_file);
|
| - CHECK(minidump.Read());
|
| -
|
| - MinidumpException *exception = minidump.GetException();
|
| - CHECK(exception);
|
| -
|
| - MinidumpContext* crash_context = exception->GetContext();
|
| - CHECK(crash_context);
|
| -
|
| - u_int32_t exception_thread_id = 0;
|
| - CHECK(exception->GetThreadID(&exception_thread_id));
|
| -
|
| - MinidumpThreadList* thread_list = minidump.GetThreadList();
|
| - CHECK(thread_list);
|
| -
|
| - MinidumpThread* exception_thread =
|
| - thread_list->GetThreadByID(exception_thread_id);
|
| - CHECK(exception_thread);
|
| -
|
| - // Currently only 32-bit Windows minidumps are supported.
|
| - CHECK_EQ(MD_CONTEXT_X86, crash_context->GetContextCPU());
|
| -
|
| - const MDRawContextX86* contextX86 = crash_context->GetContextX86();
|
| - CHECK(contextX86);
|
| -
|
| - const u_int32_t esp = contextX86->esp;
|
| -
|
| - MinidumpMemoryRegion* memory_region = exception_thread->GetMemory();
|
| - CHECK(memory_region);
|
| -
|
| - const u_int64_t last = memory_region->GetBase() + memory_region->GetSize();
|
| -
|
| - u_int64_t heap_stats_addr = 0;
|
| - for (u_int64_t addr = esp; addr < last; addr += 4) {
|
| - u_int32_t value = 0;
|
| - CHECK(memory_region->GetMemoryAtAddress(addr, &value));
|
| - if (value >= esp && value < last) {
|
| - u_int32_t value2 = 0;
|
| - CHECK(memory_region->GetMemoryAtAddress(value, &value2));
|
| - if (value2 == v8::internal::HeapStats::kStartMarker) {
|
| - heap_stats_addr = addr;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - CHECK(heap_stats_addr);
|
| -
|
| - // Read heap stats.
|
| -
|
| -#define READ_FIELD(offset) \
|
| - ReadPointedValue(memory_region, heap_stats_addr, offset)
|
| -
|
| - CHECK(READ_FIELD(0) == v8::internal::HeapStats::kStartMarker);
|
| - CHECK(READ_FIELD(24) == v8::internal::HeapStats::kEndMarker);
|
| -
|
| - const int new_space_size = READ_FIELD(1);
|
| - const int new_space_capacity = READ_FIELD(2);
|
| - const int old_space_size = READ_FIELD(3);
|
| - const int old_space_capacity = READ_FIELD(4);
|
| - const int code_space_size = READ_FIELD(5);
|
| - const int code_space_capacity = READ_FIELD(6);
|
| - const int map_space_size = READ_FIELD(7);
|
| - const int map_space_capacity = READ_FIELD(8);
|
| - const int cell_space_size = READ_FIELD(9);
|
| - const int cell_space_capacity = READ_FIELD(10);
|
| - const int lo_space_size = READ_FIELD(11);
|
| - const int global_handle_count = READ_FIELD(12);
|
| - const int weak_global_handle_count = READ_FIELD(13);
|
| - const int pending_global_handle_count = READ_FIELD(14);
|
| - const int near_death_global_handle_count = READ_FIELD(15);
|
| - const int destroyed_global_handle_count = READ_FIELD(16);
|
| - const int memory_allocator_size = READ_FIELD(17);
|
| - const int memory_allocator_capacity = READ_FIELD(18);
|
| - const int os_error = READ_FIELD(19);
|
| -#undef READ_FIELD
|
| -
|
| - int objects_per_type[v8::internal::LAST_TYPE + 1] = {0};
|
| - ReadArrayFrom(memory_region, heap_stats_addr, 21,
|
| - v8::internal::LAST_TYPE + 1, objects_per_type);
|
| -
|
| - int size_per_type[v8::internal::LAST_TYPE + 1] = {0};
|
| - ReadArrayFrom(memory_region, heap_stats_addr, 22, v8::internal::LAST_TYPE + 1,
|
| - size_per_type);
|
| -
|
| - int js_global_objects =
|
| - objects_per_type[v8::internal::JS_GLOBAL_OBJECT_TYPE];
|
| - int js_builtins_objects =
|
| - objects_per_type[v8::internal::JS_BUILTINS_OBJECT_TYPE];
|
| - int js_global_proxies =
|
| - objects_per_type[v8::internal::JS_GLOBAL_PROXY_TYPE];
|
| -
|
| - int indices[v8::internal::LAST_TYPE + 1];
|
| - for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
|
| - indices[i] = i;
|
| - }
|
| -
|
| - std::stable_sort(indices, indices + sizeof(indices)/sizeof(indices[0]),
|
| - IndirectSorter(size_per_type));
|
| -
|
| - int total_size = 0;
|
| - for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
|
| - total_size += size_per_type[i];
|
| - }
|
| -
|
| - // Print heap stats.
|
| -
|
| - printf("exception thread ID: %" PRIu32 " (%#" PRIx32 ")\n",
|
| - exception_thread_id, exception_thread_id);
|
| - printf("heap stats address: %#" PRIx64 "\n", heap_stats_addr);
|
| -#define PRINT_INT_STAT(stat) \
|
| - printf("\t%-25s\t% 10d\n", #stat ":", stat);
|
| -#define PRINT_MB_STAT(stat) \
|
| - printf("\t%-25s\t% 10.3f MB\n", #stat ":", toM(stat));
|
| - PRINT_MB_STAT(new_space_size);
|
| - PRINT_MB_STAT(new_space_capacity);
|
| - PRINT_MB_STAT(old_space_size);
|
| - PRINT_MB_STAT(old_space_capacity);
|
| - PRINT_MB_STAT(code_space_size);
|
| - PRINT_MB_STAT(code_space_capacity);
|
| - PRINT_MB_STAT(map_space_size);
|
| - PRINT_MB_STAT(map_space_capacity);
|
| - PRINT_MB_STAT(cell_space_size);
|
| - PRINT_MB_STAT(cell_space_capacity);
|
| - PRINT_MB_STAT(lo_space_size);
|
| - PRINT_INT_STAT(global_handle_count);
|
| - PRINT_INT_STAT(weak_global_handle_count);
|
| - PRINT_INT_STAT(pending_global_handle_count);
|
| - PRINT_INT_STAT(near_death_global_handle_count);
|
| - PRINT_INT_STAT(destroyed_global_handle_count);
|
| - PRINT_MB_STAT(memory_allocator_size);
|
| - PRINT_MB_STAT(memory_allocator_capacity);
|
| - PRINT_INT_STAT(os_error);
|
| -#undef PRINT_STAT
|
| -
|
| - printf("\n");
|
| -
|
| - printf(
|
| - "\tJS_GLOBAL_OBJECT_TYPE/JS_BUILTINS_OBJECT_TYPE/JS_GLOBAL_PROXY_TYPE: "
|
| - "%d/%d/%d\n\n",
|
| - js_global_objects, js_builtins_objects, js_global_proxies);
|
| -
|
| - int running_size = 0;
|
| - for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
|
| - int type = indices[i];
|
| - const char* name = InstanceTypeToString(type);
|
| - if (name == NULL) {
|
| - // Unknown instance type. Check that there is no objects of that type.
|
| - CHECK_EQ(0, objects_per_type[type]);
|
| - CHECK_EQ(0, size_per_type[type]);
|
| - continue;
|
| - }
|
| - int size = size_per_type[type];
|
| - running_size += size;
|
| - printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n",
|
| - name, objects_per_type[type], toM(size),
|
| - 100. * size / total_size, 100. * running_size / total_size);
|
| - }
|
| - printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n",
|
| - "total", 0, toM(total_size), 100., 100.);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -int main(int argc, char **argv) {
|
| - if (argc != 2) {
|
| - fprintf(stderr, "usage: %s <minidump>\n", argv[0]);
|
| - return 1;
|
| - }
|
| -
|
| - DumpHeapStats(argv[1]);
|
| -
|
| - return 0;
|
| -}
|
|
|