OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2011 the V8 project authors. All rights reserved. | 3 # Copyright 2011 the V8 project authors. All rights reserved. |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 print >>sys.stderr, "Warning: unsupported minidump header magic" | 284 print >>sys.stderr, "Warning: unsupported minidump header magic" |
285 DebugPrint(self.header) | 285 DebugPrint(self.header) |
286 directories = [] | 286 directories = [] |
287 offset = self.header.stream_directories_rva | 287 offset = self.header.stream_directories_rva |
288 for _ in xrange(self.header.stream_count): | 288 for _ in xrange(self.header.stream_count): |
289 directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset)) | 289 directories.append(MINIDUMP_DIRECTORY.Read(self.minidump, offset)) |
290 offset += MINIDUMP_DIRECTORY.size | 290 offset += MINIDUMP_DIRECTORY.size |
291 self.exception = None | 291 self.exception = None |
292 self.exception_context = None | 292 self.exception_context = None |
293 self.memory_list = None | 293 self.memory_list = None |
| 294 self.memory_list64 = None |
294 self.thread_map = {} | 295 self.thread_map = {} |
295 for d in directories: | 296 for d in directories: |
296 DebugPrint(d) | 297 DebugPrint(d) |
297 # TODO(vitalyr): extract system info including CPU features. | 298 # TODO(vitalyr): extract system info including CPU features. |
298 if d.stream_type == MD_EXCEPTION_STREAM: | 299 if d.stream_type == MD_EXCEPTION_STREAM: |
299 self.exception = MINIDUMP_EXCEPTION_STREAM.Read( | 300 self.exception = MINIDUMP_EXCEPTION_STREAM.Read( |
300 self.minidump, d.location.rva) | 301 self.minidump, d.location.rva) |
301 DebugPrint(self.exception) | 302 DebugPrint(self.exception) |
302 self.exception_context = MINIDUMP_CONTEXT_X86.Read( | 303 self.exception_context = MINIDUMP_CONTEXT_X86.Read( |
303 self.minidump, self.exception.thread_context.rva) | 304 self.minidump, self.exception.thread_context.rva) |
304 DebugPrint(self.exception_context) | 305 DebugPrint(self.exception_context) |
305 elif d.stream_type == MD_THREAD_LIST_STREAM: | 306 elif d.stream_type == MD_THREAD_LIST_STREAM: |
306 thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva) | 307 thread_list = MINIDUMP_THREAD_LIST.Read(self.minidump, d.location.rva) |
307 assert ctypes.sizeof(thread_list) == d.location.data_size | 308 assert ctypes.sizeof(thread_list) == d.location.data_size |
308 DebugPrint(thread_list) | 309 DebugPrint(thread_list) |
309 for thread in thread_list.threads: | 310 for thread in thread_list.threads: |
310 DebugPrint(thread) | 311 DebugPrint(thread) |
311 self.thread_map[thread.id] = thread | 312 self.thread_map[thread.id] = thread |
312 elif d.stream_type == MD_MEMORY_LIST_STREAM: | 313 elif d.stream_type == MD_MEMORY_LIST_STREAM: |
313 print >>sys.stderr, "Warning: not a full minidump" | 314 print >>sys.stderr, "Warning: not a full minidump" |
314 ml = MINIDUMP_MEMORY_LIST.Read(self.minidump, d.location.rva) | |
315 DebugPrint(ml) | |
316 for m in ml.ranges: | |
317 DebugPrint(m) | |
318 elif d.stream_type == MD_MEMORY_64_LIST_STREAM: | |
319 assert self.memory_list is None | 315 assert self.memory_list is None |
320 self.memory_list = MINIDUMP_MEMORY_LIST64.Read( | 316 self.memory_list = MINIDUMP_MEMORY_LIST.Read( |
321 self.minidump, d.location.rva) | 317 self.minidump, d.location.rva) |
322 assert ctypes.sizeof(self.memory_list) == d.location.data_size | 318 assert ctypes.sizeof(self.memory_list) == d.location.data_size |
323 DebugPrint(self.memory_list) | 319 DebugPrint(self.memory_list) |
| 320 elif d.stream_type == MD_MEMORY_64_LIST_STREAM: |
| 321 assert self.memory_list64 is None |
| 322 self.memory_list64 = MINIDUMP_MEMORY_LIST64.Read( |
| 323 self.minidump, d.location.rva) |
| 324 assert ctypes.sizeof(self.memory_list64) == d.location.data_size |
| 325 DebugPrint(self.memory_list64) |
324 | 326 |
325 def IsValidAddress(self, address): | 327 def IsValidAddress(self, address): |
326 return self.FindLocation(address) is not None | 328 return self.FindLocation(address) is not None |
327 | 329 |
328 def ReadU8(self, address): | 330 def ReadU8(self, address): |
329 location = self.FindLocation(address) | 331 location = self.FindLocation(address) |
330 return ctypes.c_uint8.from_buffer(self.minidump, location).value | 332 return ctypes.c_uint8.from_buffer(self.minidump, location).value |
331 | 333 |
332 def ReadU32(self, address): | 334 def ReadU32(self, address): |
333 location = self.FindLocation(address) | 335 location = self.FindLocation(address) |
334 return ctypes.c_uint32.from_buffer(self.minidump, location).value | 336 return ctypes.c_uint32.from_buffer(self.minidump, location).value |
335 | 337 |
336 def ReadBytes(self, address, size): | 338 def ReadBytes(self, address, size): |
337 location = self.FindLocation(address) | 339 location = self.FindLocation(address) |
338 return self.minidump[location:location + size] | 340 return self.minidump[location:location + size] |
339 | 341 |
340 def FindLocation(self, address): | 342 def FindLocation(self, address): |
341 # TODO(vitalyr): only works for full minidumps (...64 structure variants). | |
342 offset = 0 | 343 offset = 0 |
343 for r in self.memory_list.ranges: | 344 if self.memory_list64 is not None: |
344 if r.start <= address < r.start + r.size: | 345 for r in self.memory_list64.ranges: |
345 return self.memory_list.base_rva + offset + address - r.start | 346 if r.start <= address < r.start + r.size: |
| 347 return self.memory_list64.base_rva + offset + address - r.start |
346 offset += r.size | 348 offset += r.size |
| 349 if self.memory_list is not None: |
| 350 for r in self.memory_list.ranges: |
| 351 if r.start <= address < r.start + r.memory.data_size: |
| 352 return r.memory.rva + address - r.start |
347 return None | 353 return None |
348 | 354 |
349 def GetDisasmLines(self, address, size): | 355 def GetDisasmLines(self, address, size): |
350 location = self.FindLocation(address) | 356 location = self.FindLocation(address) |
351 if location is None: return [] | 357 if location is None: return [] |
352 return disasm.GetDisasmLines(self.minidump_name, | 358 return disasm.GetDisasmLines(self.minidump_name, |
353 location, | 359 location, |
354 size, | 360 size, |
355 "ia32", | 361 "ia32", |
356 False) | 362 False) |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 reader.Dispose() | 840 reader.Dispose() |
835 | 841 |
836 | 842 |
837 if __name__ == "__main__": | 843 if __name__ == "__main__": |
838 parser = optparse.OptionParser(USAGE) | 844 parser = optparse.OptionParser(USAGE) |
839 options, args = parser.parse_args() | 845 options, args = parser.parse_args() |
840 if len(args) != 1: | 846 if len(args) != 1: |
841 parser.print_help() | 847 parser.print_help() |
842 sys.exit(1) | 848 sys.exit(1) |
843 AnalyzeMinidump(options, args[0]) | 849 AnalyzeMinidump(options, args[0]) |
OLD | NEW |