OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
11 // with the distribution. | 11 // with the distribution. |
12 // * Neither the name of Google Inc. nor the names of its | 12 // * Neither the name of Google Inc. nor the names of its |
13 // contributors may be used to endorse or promote products derived | 13 // contributors may be used to endorse or promote products derived |
14 // from this software without specific prior written permission. | 14 // from this software without specific prior written permission. |
15 // | 15 // |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include <algorithm> | |
29 #include <stdio.h> | 28 #include <stdio.h> |
30 #include <stdlib.h> | 29 #include <stdlib.h> |
31 | 30 |
| 31 #include <algorithm> |
| 32 |
32 #include <google_breakpad/processor/minidump.h> | 33 #include <google_breakpad/processor/minidump.h> |
33 #include <processor/logging.h> | |
34 | 34 |
35 #define ENABLE_DEBUGGER_SUPPORT | 35 #define ENABLE_DEBUGGER_SUPPORT |
36 | 36 |
37 #include <v8.h> | 37 #include <v8.h> |
38 | 38 |
39 namespace { | 39 namespace { |
40 | 40 |
41 using google_breakpad::Minidump; | 41 using google_breakpad::Minidump; |
42 using google_breakpad::MinidumpContext; | 42 using google_breakpad::MinidumpContext; |
43 using google_breakpad::MinidumpThread; | 43 using google_breakpad::MinidumpThread; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
121 u_int32_t exception_thread_id = 0; | 121 u_int32_t exception_thread_id = 0; |
122 CHECK(exception->GetThreadID(&exception_thread_id)); | 122 CHECK(exception->GetThreadID(&exception_thread_id)); |
123 | 123 |
124 MinidumpThreadList* thread_list = minidump.GetThreadList(); | 124 MinidumpThreadList* thread_list = minidump.GetThreadList(); |
125 CHECK(thread_list); | 125 CHECK(thread_list); |
126 | 126 |
127 MinidumpThread* exception_thread = | 127 MinidumpThread* exception_thread = |
128 thread_list->GetThreadByID(exception_thread_id); | 128 thread_list->GetThreadByID(exception_thread_id); |
129 CHECK(exception_thread); | 129 CHECK(exception_thread); |
130 | 130 |
| 131 // Currently only 32-bit Windows minidumps are supported. |
| 132 CHECK_EQ(MD_CONTEXT_X86, crash_context->GetContextCPU()); |
| 133 |
131 const MDRawContextX86* contextX86 = crash_context->GetContextX86(); | 134 const MDRawContextX86* contextX86 = crash_context->GetContextX86(); |
132 CHECK(contextX86); | 135 CHECK(contextX86); |
133 | 136 |
134 const u_int32_t esp = contextX86->esp; | 137 const u_int32_t esp = contextX86->esp; |
135 | 138 |
136 MinidumpMemoryRegion* memory_region = exception_thread->GetMemory(); | 139 MinidumpMemoryRegion* memory_region = exception_thread->GetMemory(); |
137 CHECK(memory_region); | 140 CHECK(memory_region); |
138 | 141 |
139 const u_int64_t last = memory_region->GetBase() + memory_region->GetSize(); | 142 const u_int64_t last = memory_region->GetBase() + memory_region->GetSize(); |
140 | 143 |
141 u_int64_t heap_stats_addr = 0; | 144 u_int64_t heap_stats_addr = 0; |
142 for (u_int64_t addr = esp; addr < last; addr += 4) { | 145 for (u_int64_t addr = esp; addr < last; addr += 4) { |
143 u_int32_t value = 0; | 146 u_int32_t value = 0; |
144 CHECK(memory_region->GetMemoryAtAddress(addr, &value)); | 147 CHECK(memory_region->GetMemoryAtAddress(addr, &value)); |
145 if (value >= esp && value < last) { | 148 if (value >= esp && value < last) { |
146 u_int32_t value2 = 0; | 149 u_int32_t value2 = 0; |
147 CHECK(memory_region->GetMemoryAtAddress(value, &value2)); | 150 CHECK(memory_region->GetMemoryAtAddress(value, &value2)); |
148 if (value2 == 0xdecade00) { | 151 if (value2 == v8::internal::HeapStats::kStartMarker) { |
149 heap_stats_addr = addr; | 152 heap_stats_addr = addr; |
150 break; | 153 break; |
151 } | 154 } |
152 } | 155 } |
153 } | 156 } |
154 CHECK(heap_stats_addr); | 157 CHECK(heap_stats_addr); |
155 | 158 |
156 // Read heap stats. | 159 // Read heap stats. |
157 | 160 |
158 #define READ_FIELD(offset) \ | 161 #define READ_FIELD(offset) \ |
159 ReadPointedValue(memory_region, heap_stats_addr, offset) | 162 ReadPointedValue(memory_region, heap_stats_addr, offset) |
160 | 163 |
161 CHECK(READ_FIELD(0) == 0xdecade00); | 164 CHECK(READ_FIELD(0) == v8::internal::HeapStats::kStartMarker); |
162 CHECK(READ_FIELD(23) == 0xdecade01); | 165 CHECK(READ_FIELD(23) == v8::internal::HeapStats::kEndMarker); |
163 | 166 |
164 const int new_space_size = READ_FIELD(1); | 167 const int new_space_size = READ_FIELD(1); |
165 const int new_space_capacity = READ_FIELD(2); | 168 const int new_space_capacity = READ_FIELD(2); |
166 const int old_pointer_space_size = READ_FIELD(3); | 169 const int old_pointer_space_size = READ_FIELD(3); |
167 const int old_pointer_space_capacity = READ_FIELD(4); | 170 const int old_pointer_space_capacity = READ_FIELD(4); |
168 const int old_data_space_size = READ_FIELD(5); | 171 const int old_data_space_size = READ_FIELD(5); |
169 const int old_data_space_capacity = READ_FIELD(6); | 172 const int old_data_space_capacity = READ_FIELD(6); |
170 const int code_space_size = READ_FIELD(7); | 173 const int code_space_size = READ_FIELD(7); |
171 const int code_space_capacity = READ_FIELD(8); | 174 const int code_space_capacity = READ_FIELD(8); |
172 const int map_space_size = READ_FIELD(9); | 175 const int map_space_size = READ_FIELD(9); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 std::stable_sort(indices, indices + sizeof(indices)/sizeof(indices[0]), | 209 std::stable_sort(indices, indices + sizeof(indices)/sizeof(indices[0]), |
207 IndirectSorter(size_per_type)); | 210 IndirectSorter(size_per_type)); |
208 | 211 |
209 int total_size = 0; | 212 int total_size = 0; |
210 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) { | 213 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) { |
211 total_size += size_per_type[i]; | 214 total_size += size_per_type[i]; |
212 } | 215 } |
213 | 216 |
214 // Print heap stats. | 217 // Print heap stats. |
215 | 218 |
216 printf("exception thread ID: %d (%x)\n", | 219 printf("exception thread ID: %" PRIu32 " (%#" PRIx32 ")\n", |
217 exception_thread_id, exception_thread_id); | 220 exception_thread_id, exception_thread_id); |
218 printf("heap stats address: %p\n", (void*)heap_stats_addr); | 221 printf("heap stats address: %#" PRIx64 "\n", heap_stats_addr); |
219 #define PRINT_INT_STAT(stat) \ | 222 #define PRINT_INT_STAT(stat) \ |
220 printf("\t%-25s\t% 10d\n", #stat ":", stat); | 223 printf("\t%-25s\t% 10d\n", #stat ":", stat); |
221 #define PRINT_MB_STAT(stat) \ | 224 #define PRINT_MB_STAT(stat) \ |
222 printf("\t%-25s\t% 10.3f MB\n", #stat ":", toM(stat)); | 225 printf("\t%-25s\t% 10.3f MB\n", #stat ":", toM(stat)); |
223 PRINT_MB_STAT(new_space_size); | 226 PRINT_MB_STAT(new_space_size); |
224 PRINT_MB_STAT(new_space_capacity); | 227 PRINT_MB_STAT(new_space_capacity); |
225 PRINT_MB_STAT(old_pointer_space_size); | 228 PRINT_MB_STAT(old_pointer_space_size); |
226 PRINT_MB_STAT(old_pointer_space_capacity); | 229 PRINT_MB_STAT(old_pointer_space_capacity); |
227 PRINT_MB_STAT(old_data_space_size); | 230 PRINT_MB_STAT(old_data_space_size); |
228 PRINT_MB_STAT(old_data_space_capacity); | 231 PRINT_MB_STAT(old_data_space_capacity); |
(...skipping 19 matching lines...) Expand all Loading... |
248 "\tJS_GLOBAL_OBJECT_TYPE/JS_BUILTINS_OBJECT_TYPE/JS_GLOBAL_PROXY_TYPE: " | 251 "\tJS_GLOBAL_OBJECT_TYPE/JS_BUILTINS_OBJECT_TYPE/JS_GLOBAL_PROXY_TYPE: " |
249 "%d/%d/%d\n\n", | 252 "%d/%d/%d\n\n", |
250 js_global_objects, js_builtins_objects, js_global_proxies); | 253 js_global_objects, js_builtins_objects, js_global_proxies); |
251 | 254 |
252 int running_size = 0; | 255 int running_size = 0; |
253 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) { | 256 for (int i = 0; i <= v8::internal::LAST_TYPE; i++) { |
254 int type = indices[i]; | 257 int type = indices[i]; |
255 const char* name = InstanceTypeToString(type); | 258 const char* name = InstanceTypeToString(type); |
256 if (name == NULL) { | 259 if (name == NULL) { |
257 // Unknown instance type. Check that there is no objects of that type. | 260 // Unknown instance type. Check that there is no objects of that type. |
258 CHECK(objects_per_type[type] == 0); | 261 CHECK_EQ(0, objects_per_type[type]); |
259 CHECK(size_per_type[type] == 0); | 262 CHECK_EQ(0, size_per_type[type]); |
260 continue; | 263 continue; |
261 } | 264 } |
262 int size = size_per_type[type]; | 265 int size = size_per_type[type]; |
263 running_size += size; | 266 running_size += size; |
264 printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n", | 267 printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n", |
265 name, objects_per_type[type], toM(size), | 268 name, objects_per_type[type], toM(size), |
266 100.*size/total_size, 100.*running_size/total_size); | 269 100. * size / total_size, 100. * running_size / total_size); |
267 } | 270 } |
268 printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n", | 271 printf("\t%-37s% 9d% 11.3f MB% 10.3f%%% 10.3f%%\n", |
269 "total", 0, toM(total_size), 100., 100.); | 272 "total", 0, toM(total_size), 100., 100.); |
270 } | 273 } |
271 | 274 |
272 } // namespace | 275 } // namespace |
273 | 276 |
274 int main(int argc, char **argv) { | 277 int main(int argc, char **argv) { |
275 BPLOG_INIT(&argc, &argv); | |
276 | |
277 if (argc != 2) { | 278 if (argc != 2) { |
278 fprintf(stderr, "usage: %s <minidump>\n", argv[0]); | 279 fprintf(stderr, "usage: %s <minidump>\n", argv[0]); |
279 return 1; | 280 return 1; |
280 } | 281 } |
281 | 282 |
282 DumpHeapStats(argv[1]); | 283 DumpHeapStats(argv[1]); |
283 | 284 |
284 return 0; | 285 return 0; |
285 } | 286 } |
OLD | NEW |