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

Side by Side Diff: tools/oom_dump/oom_dump.cc

Issue 3170015: Initial implementation of oom_dump utility. (Closed)
Patch Set: Addressing Mads' comments Created 10 years, 4 months 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 unified diff | Download patch
« tools/oom_dump/README ('K') | « tools/oom_dump/SConstruct ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include <algorithm>
Mark Mentovai 2010/08/16 20:56:43 The style guide says: C system headers first, then
antonm 2010/08/17 13:13:19 Done. Also removed some now unnecessary deps.
29 #include <stdio.h>
30 #include <stdlib.h>
31
32 #include <google_breakpad/processor/minidump.h>
33 #include <processor/logging.h>
34
35 #define ENABLE_DEBUGGER_SUPPORT
36
37 #include <v8.h>
38
39 namespace {
40
41 using google_breakpad::Minidump;
42 using google_breakpad::MinidumpContext;
43 using google_breakpad::MinidumpThread;
44 using google_breakpad::MinidumpThreadList;
45 using google_breakpad::MinidumpException;
46 using google_breakpad::MinidumpMemoryRegion;
47
48 const char* InstanceTypeToString(int type) {
49 static char const* names[v8::internal::LAST_TYPE] = {0};
50 if (names[v8::internal::STRING_TYPE] == NULL) {
51 using namespace v8::internal;
52 #define SET(type) names[type] = #type;
53 INSTANCE_TYPE_LIST(SET)
54 #undef SET
55 }
56 return names[type];
57 }
58
59
60 u_int32_t ReadPointedValue(MinidumpMemoryRegion* region,
61 u_int64_t base,
62 int offset) {
63 u_int32_t ptr = 0;
64 CHECK(region->GetMemoryAtAddress(base + 4 * offset, &ptr));
65 u_int32_t value = 0;
66 CHECK(region->GetMemoryAtAddress(ptr, &value));
67 return value;
68 }
69
70
71 void ReadArray(MinidumpMemoryRegion* region,
72 u_int64_t array_ptr,
73 int size,
74 int* output) {
75 for (int i = 0; i < size; i++) {
76 u_int32_t value;
77 CHECK(region->GetMemoryAtAddress(array_ptr + 4 * i, &value));
78 output[i] = value;
79 }
80 }
81
82
83 u_int32_t ReadArrayFrom(MinidumpMemoryRegion* region,
84 u_int64_t base,
85 int offset,
86 int size,
87 int* output) {
88 u_int32_t ptr = 0;
89 CHECK(region->GetMemoryAtAddress(base + 4 * offset, &ptr));
90 ReadArray(region, ptr, size, output);
91 }
92
93
94 double toM(int size) {
95 return size / (1024. * 1024.);
96 }
97
98
99 class IndirectSorter {
100 public:
101 explicit IndirectSorter(int* a) : a_(a) { }
102
103 bool operator() (int i0, int i1) {
104 return a_[i0] > a_[i1];
105 }
106
107 private:
108 int* a_;
109 };
110
111 void DumpHeapStats(const char *minidump_file) {
112 Minidump minidump(minidump_file);
113 CHECK(minidump.Read());
114
115 MinidumpException *exception = minidump.GetException();
116 CHECK(exception);
117
118 MinidumpContext* crash_context = exception->GetContext();
119 CHECK(crash_context);
120
121 u_int32_t exception_thread_id = 0;
122 CHECK(exception->GetThreadID(&exception_thread_id));
123
124 MinidumpThreadList* thread_list = minidump.GetThreadList();
125 CHECK(thread_list);
126
127 MinidumpThread* exception_thread =
128 thread_list->GetThreadByID(exception_thread_id);
129 CHECK(exception_thread);
130
131 const MDRawContextX86* contextX86 = crash_context->GetContextX86();
Mark Mentovai 2010/08/16 20:56:43 Have you tried this with non-x86 dumps? Does it wo
antonm 2010/08/17 13:13:19 Mark, my bad---I didn't make it explicit what is e
132 CHECK(contextX86);
133
134 const u_int32_t esp = contextX86->esp;
135
136 MinidumpMemoryRegion* memory_region = exception_thread->GetMemory();
137 CHECK(memory_region);
138
139 const u_int64_t last = memory_region->GetBase() + memory_region->GetSize();
140
141 u_int64_t heap_stats_addr = 0;
142 for (u_int64_t addr = esp; addr < last; addr += 4) {
143 u_int32_t value = 0;
144 CHECK(memory_region->GetMemoryAtAddress(addr, &value));
145 if (value >= esp && value < last) {
146 u_int32_t value2 = 0;
147 CHECK(memory_region->GetMemoryAtAddress(value, &value2));
148 if (value2 == 0xdecade00) {
Mark Mentovai 2010/08/16 20:56:43 This might be better as a symbolic constant, like
antonm 2010/08/17 13:13:19 Done.
149 heap_stats_addr = addr;
150 break;
151 }
152 }
153 }
154 CHECK(heap_stats_addr);
155
156 // Read heap stats.
157
158 #define READ_FIELD(offset) \
159 ReadPointedValue(memory_region, heap_stats_addr, offset)
160
161 CHECK(READ_FIELD(0) == 0xdecade00);
162 CHECK(READ_FIELD(23) == 0xdecade01);
163
164 const int new_space_size = READ_FIELD(1);
Mark Mentovai 2010/08/16 20:56:43 Is a native "int" correct? Are these fields fixed
antonm 2010/08/17 13:13:19 They are declared as plain ints: http://www.google
165 const int new_space_capacity = READ_FIELD(2);
166 const int old_pointer_space_size = READ_FIELD(3);
167 const int old_pointer_space_capacity = READ_FIELD(4);
168 const int old_data_space_size = READ_FIELD(5);
169 const int old_data_space_capacity = READ_FIELD(6);
170 const int code_space_size = READ_FIELD(7);
171 const int code_space_capacity = READ_FIELD(8);
172 const int map_space_size = READ_FIELD(9);
173 const int map_space_capacity = READ_FIELD(10);
174 const int cell_space_size = READ_FIELD(11);
175 const int cell_space_capacity = READ_FIELD(12);
176 const int lo_space_size = READ_FIELD(13);
177 const int global_handle_count = READ_FIELD(14);
178 const int weak_global_handle_count = READ_FIELD(15);
179 const int pending_global_handle_count = READ_FIELD(16);
180 const int near_death_global_handle_count = READ_FIELD(17);
181 const int destroyed_global_handle_count = READ_FIELD(18);
182 const int memory_allocator_size = READ_FIELD(19);
183 const int memory_allocator_capacity = READ_FIELD(20);
184 #undef READ_FIELD
185
186 int objects_per_type[v8::internal::LAST_TYPE + 1] = {0};
187 ReadArrayFrom(memory_region, heap_stats_addr, 21,
188 v8::internal::LAST_TYPE + 1, objects_per_type);
189
190 int size_per_type[v8::internal::LAST_TYPE + 1] = {0};
191 ReadArrayFrom(memory_region, heap_stats_addr, 22, v8::internal::LAST_TYPE + 1,
192 size_per_type);
193
194 int js_global_objects =
195 objects_per_type[v8::internal::JS_GLOBAL_OBJECT_TYPE];
196 int js_builtins_objects =
197 objects_per_type[v8::internal::JS_BUILTINS_OBJECT_TYPE];
198 int js_global_proxies =
199 objects_per_type[v8::internal::JS_GLOBAL_PROXY_TYPE];
200
201 int indices[v8::internal::LAST_TYPE + 1];
202 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
203 indices[i] = i;
204 }
205
206 std::stable_sort(indices, indices + sizeof(indices)/sizeof(indices[0]),
207 IndirectSorter(size_per_type));
208
209 int total_size = 0;
210 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
211 total_size += size_per_type[i];
212 }
213
214 // Print heap stats.
215
216 printf("exception thread ID: %d (%x)\n",
Mark Mentovai 2010/08/16 20:56:43 suggest 0x%x instead of just raw %x. Actually, yo
antonm 2010/08/17 13:13:19 I wasn't sure those a portable enough, but as GCC
217 exception_thread_id, exception_thread_id);
218 printf("heap stats address: %p\n", (void*)heap_stats_addr);
Mark Mentovai 2010/08/16 20:56:43 Unlike the previous one, this one's an even bigger
antonm 2010/08/17 13:13:19 Done.
219 #define PRINT_INT_STAT(stat) \
220 printf("\t%-25s\t% 10d\n", #stat ":", stat);
Mark Mentovai 2010/08/16 20:56:43 These are OK if a native "int" is correct (see abo
antonm 2010/08/17 13:13:19 They should be.
221 #define PRINT_MB_STAT(stat) \
222 printf("\t%-25s\t% 10.3f MB\n", #stat ":", toM(stat));
223 PRINT_MB_STAT(new_space_size);
224 PRINT_MB_STAT(new_space_capacity);
225 PRINT_MB_STAT(old_pointer_space_size);
226 PRINT_MB_STAT(old_pointer_space_capacity);
227 PRINT_MB_STAT(old_data_space_size);
228 PRINT_MB_STAT(old_data_space_capacity);
229 PRINT_MB_STAT(code_space_size);
230 PRINT_MB_STAT(code_space_capacity);
231 PRINT_MB_STAT(map_space_size);
232 PRINT_MB_STAT(map_space_capacity);
233 PRINT_MB_STAT(cell_space_size);
234 PRINT_MB_STAT(cell_space_capacity);
235 PRINT_MB_STAT(lo_space_size);
236 PRINT_INT_STAT(global_handle_count);
237 PRINT_INT_STAT(weak_global_handle_count);
238 PRINT_INT_STAT(pending_global_handle_count);
239 PRINT_INT_STAT(near_death_global_handle_count);
240 PRINT_INT_STAT(destroyed_global_handle_count);
241 PRINT_MB_STAT(memory_allocator_size);
242 PRINT_MB_STAT(memory_allocator_capacity);
243 #undef PRINT_STAT
244
245 printf("\n");
246
247 printf(
248 "\tJS_GLOBAL_OBJECT_TYPE/JS_BUILTINS_OBJECT_TYPE/JS_GLOBAL_PROXY_TYPE: "
249 "%d/%d/%d\n\n",
250 js_global_objects, js_builtins_objects, js_global_proxies);
251
252 int running_size = 0;
253 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) {
254 int type = indices[i];
255 const char* name = InstanceTypeToString(type);
256 if (name == NULL) {
257 // Unknown instance type. Check that there is no objects of that type.
258 CHECK(objects_per_type[type] == 0);
259 CHECK(size_per_type[type] == 0);
260 continue;
261 }
262 int size = size_per_type[type];
263 running_size += size;
264 printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n",
265 name, objects_per_type[type], toM(size),
266 100.*size/total_size, 100.*running_size/total_size);
267 }
268 printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n",
269 "total", 0, toM(total_size), 100., 100.);
270 }
271
272 } // namespace
273
274 int main(int argc, char **argv) {
275 BPLOG_INIT(&argc, &argv);
276
277 if (argc != 2) {
278 fprintf(stderr, "usage: %s <minidump>\n", argv[0]);
279 return 1;
280 }
281
282 DumpHeapStats(argv[1]);
283
284 return 0;
285 }
OLDNEW
« tools/oom_dump/README ('K') | « tools/oom_dump/SConstruct ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698