@@ -296,6 +296,42 @@ def EnableOnFlag(type, flag):
296
296
MD_CONTEXT_X86_EXTENDED_REGISTERS ))
297
297
])
298
298
299
+ MD_CONTEXT_ARM = 0x40000000
300
+ MD_CONTEXT_ARM_INTEGER = (MD_CONTEXT_ARM | 0x00000002 )
301
+ MD_CONTEXT_ARM_FLOATING_POINT = (MD_CONTEXT_ARM | 0x00000004 )
302
+ MD_FLOATINGSAVEAREA_ARM_FPR_COUNT = 32
303
+ MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT = 8
304
+
305
+ MINIDUMP_FLOATING_SAVE_AREA_ARM = Descriptor ([
306
+ ("fpscr" , ctypes .c_uint64 ),
307
+ ("regs" , ctypes .c_uint64 * MD_FLOATINGSAVEAREA_ARM_FPR_COUNT ),
308
+ ("extra" , ctypes .c_uint64 * MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT )
309
+ ])
310
+
311
+ MINIDUMP_CONTEXT_ARM = Descriptor ([
312
+ ("context_flags" , ctypes .c_uint32 ),
313
+ # MD_CONTEXT_ARM_INTEGER.
314
+ ("r0" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
315
+ ("r1" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
316
+ ("r2" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
317
+ ("r3" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
318
+ ("r4" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
319
+ ("r5" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
320
+ ("r6" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
321
+ ("r7" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
322
+ ("r8" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
323
+ ("r9" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
324
+ ("r10" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
325
+ ("r11" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
326
+ ("r12" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
327
+ ("sp" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
328
+ ("lr" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
329
+ ("pc" , EnableOnFlag (ctypes .c_uint32 , MD_CONTEXT_ARM_INTEGER )),
330
+ ("cpsr" , ctypes .c_uint32 ),
331
+ ("float_save" , EnableOnFlag (MINIDUMP_FLOATING_SAVE_AREA_ARM .ctype ,
332
+ MD_CONTEXT_ARM_FLOATING_POINT ))
333
+ ])
334
+
299
335
MD_CONTEXT_AMD64 = 0x00100000
300
336
MD_CONTEXT_AMD64_CONTROL = (MD_CONTEXT_AMD64 | 0x00000001 )
301
337
MD_CONTEXT_AMD64_INTEGER = (MD_CONTEXT_AMD64 | 0x00000002 )
@@ -429,6 +465,7 @@ def EnableOnFlag(type, flag):
429
465
])
430
466
431
467
MD_CPU_ARCHITECTURE_X86 = 0
468
+ MD_CPU_ARCHITECTURE_ARM = 5
432
469
MD_CPU_ARCHITECTURE_AMD64 = 9
433
470
434
471
class FuncSymbol :
@@ -481,7 +518,9 @@ def __init__(self, options, minidump_name):
481
518
system_info = MINIDUMP_RAW_SYSTEM_INFO .Read (
482
519
self .minidump , d .location .rva )
483
520
self .arch = system_info .processor_architecture
484
- assert self .arch in [MD_CPU_ARCHITECTURE_AMD64 , MD_CPU_ARCHITECTURE_X86 ]
521
+ assert self .arch in [MD_CPU_ARCHITECTURE_AMD64 ,
522
+ MD_CPU_ARCHITECTURE_ARM ,
523
+ MD_CPU_ARCHITECTURE_X86 ]
485
524
assert not self .arch is None
486
525
487
526
for d in directories :
@@ -496,6 +535,9 @@ def __init__(self, options, minidump_name):
496
535
elif self .arch == MD_CPU_ARCHITECTURE_AMD64 :
497
536
self .exception_context = MINIDUMP_CONTEXT_AMD64 .Read (
498
537
self .minidump , self .exception .thread_context .rva )
538
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
539
+ self .exception_context = MINIDUMP_CONTEXT_ARM .Read (
540
+ self .minidump , self .exception .thread_context .rva )
499
541
DebugPrint (self .exception_context )
500
542
elif d .stream_type == MD_THREAD_LIST_STREAM :
501
543
thread_list = MINIDUMP_THREAD_LIST .Read (self .minidump , d .location .rva )
@@ -541,6 +583,8 @@ def ReadU64(self, address):
541
583
def ReadUIntPtr (self , address ):
542
584
if self .arch == MD_CPU_ARCHITECTURE_AMD64 :
543
585
return self .ReadU64 (address )
586
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
587
+ return self .ReadU32 (address )
544
588
elif self .arch == MD_CPU_ARCHITECTURE_X86 :
545
589
return self .ReadU32 (address )
546
590
@@ -551,6 +595,8 @@ def ReadBytes(self, address, size):
551
595
def _ReadWord (self , location ):
552
596
if self .arch == MD_CPU_ARCHITECTURE_AMD64 :
553
597
return ctypes .c_uint64 .from_buffer (self .minidump , location ).value
598
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
599
+ return ctypes .c_uint32 .from_buffer (self .minidump , location ).value
554
600
elif self .arch == MD_CPU_ARCHITECTURE_X86 :
555
601
return ctypes .c_uint32 .from_buffer (self .minidump , location ).value
556
602
@@ -647,18 +693,29 @@ def FindLocation(self, address):
647
693
return None
648
694
649
695
def GetDisasmLines (self , address , size ):
696
+ def CountUndefinedInstructions (lines ):
697
+ pattern = "<UNDEFINED>"
698
+ return sum ([line .count (pattern ) for (ignore , line ) in lines ])
699
+
650
700
location = self .FindLocation (address )
651
701
if location is None : return []
652
702
arch = None
703
+ possible_objdump_flags = ["" ]
653
704
if self .arch == MD_CPU_ARCHITECTURE_X86 :
654
705
arch = "ia32"
706
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
707
+ arch = "arm"
708
+ possible_objdump_flags = ["" , "--disassembler-options=force-thumb" ]
655
709
elif self .arch == MD_CPU_ARCHITECTURE_AMD64 :
656
710
arch = "x64"
657
- return disasm .GetDisasmLines (self .minidump_name ,
658
- location ,
659
- size ,
660
- arch ,
661
- False )
711
+ results = [ disasm .GetDisasmLines (self .minidump_name ,
712
+ location ,
713
+ size ,
714
+ arch ,
715
+ False ,
716
+ objdump_flags )
717
+ for objdump_flags in possible_objdump_flags ]
718
+ return min (results , key = CountUndefinedInstructions )
662
719
663
720
664
721
def Dispose (self ):
@@ -668,24 +725,32 @@ def Dispose(self):
668
725
def ExceptionIP (self ):
669
726
if self .arch == MD_CPU_ARCHITECTURE_AMD64 :
670
727
return self .exception_context .rip
728
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
729
+ return self .exception_context .pc
671
730
elif self .arch == MD_CPU_ARCHITECTURE_X86 :
672
731
return self .exception_context .eip
673
732
674
733
def ExceptionSP (self ):
675
734
if self .arch == MD_CPU_ARCHITECTURE_AMD64 :
676
735
return self .exception_context .rsp
736
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
737
+ return self .exception_context .sp
677
738
elif self .arch == MD_CPU_ARCHITECTURE_X86 :
678
739
return self .exception_context .esp
679
740
680
741
def FormatIntPtr (self , value ):
681
742
if self .arch == MD_CPU_ARCHITECTURE_AMD64 :
682
743
return "%016x" % value
744
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
745
+ return "%08x" % value
683
746
elif self .arch == MD_CPU_ARCHITECTURE_X86 :
684
747
return "%08x" % value
685
748
686
749
def PointerSize (self ):
687
750
if self .arch == MD_CPU_ARCHITECTURE_AMD64 :
688
751
return 8
752
+ elif self .arch == MD_CPU_ARCHITECTURE_ARM :
753
+ return 4
689
754
elif self .arch == MD_CPU_ARCHITECTURE_X86 :
690
755
return 4
691
756
@@ -1462,6 +1527,8 @@ def ObjectAlignmentMask(self):
1462
1527
def MapAlignmentMask (self ):
1463
1528
if self .reader .arch == MD_CPU_ARCHITECTURE_AMD64 :
1464
1529
return (1 << 4 ) - 1
1530
+ elif self .reader .arch == MD_CPU_ARCHITECTURE_ARM :
1531
+ return (1 << 4 ) - 1
1465
1532
elif self .reader .arch == MD_CPU_ARCHITECTURE_X86 :
1466
1533
return (1 << 5 ) - 1
1467
1534
@@ -1746,6 +1813,9 @@ def do_u(self, args):
1746
1813
MD_CPU_ARCHITECTURE_AMD64 :
1747
1814
['rax' , 'rbx' , 'rcx' , 'rdx' , 'rdi' , 'rsi' , 'rbp' , 'rsp' , 'rip' ,
1748
1815
'r8' , 'r9' , 'r10' , 'r11' , 'r12' , 'r13' , 'r14' , 'r15' ],
1816
+ MD_CPU_ARCHITECTURE_ARM :
1817
+ ['r0' , 'r1' , 'r2' , 'r3' , 'r4' , 'r5' , 'r6' , 'r7' , 'r8' , 'r9' ,
1818
+ 'r10' , 'r11' , 'r12' , 'sp' , 'lr' , 'pc' ],
1749
1819
MD_CPU_ARCHITECTURE_X86 :
1750
1820
['eax' , 'ebx' , 'ecx' , 'edx' , 'edi' , 'esi' , 'ebp' , 'esp' , 'eip' ]
1751
1821
}
@@ -1771,7 +1841,11 @@ def AnalyzeMinidump(options, minidump_name):
1771
1841
for r in CONTEXT_FOR_ARCH [reader .arch ]:
1772
1842
print " %s: %s" % (r , reader .FormatIntPtr (reader .Register (r )))
1773
1843
# TODO(vitalyr): decode eflags.
1774
- print " eflags: %s" % bin (reader .exception_context .eflags )[2 :]
1844
+ if reader .arch == MD_CPU_ARCHITECTURE_ARM :
1845
+ print " cpsr: %s" % bin (reader .exception_context .cpsr )[2 :]
1846
+ else :
1847
+ print " eflags: %s" % bin (reader .exception_context .eflags )[2 :]
1848
+
1775
1849
print
1776
1850
print " modules:"
1777
1851
for module in reader .module_list .modules :
@@ -1842,7 +1916,15 @@ def AnalyzeMinidump(options, minidump_name):
1842
1916
help = "dump all information contained in the minidump" )
1843
1917
parser .add_option ("--symdir" , dest = "symdir" , default = "." ,
1844
1918
help = "directory containing *.pdb.sym file with symbols" )
1919
+ parser .add_option ("--objdump" ,
1920
+ default = "/usr/bin/objdump" ,
1921
+ help = "objdump tool to use [default: %default]" )
1845
1922
options , args = parser .parse_args ()
1923
+ if os .path .exists (options .objdump ):
1924
+ disasm .OBJDUMP_BIN = options .objdump
1925
+ OBJDUMP_BIN = options .objdump
1926
+ else :
1927
+ print "Cannot find %s, falling back to default objdump" % options .objdump
1846
1928
if len (args ) != 1 :
1847
1929
parser .print_help ()
1848
1930
sys .exit (1 )
0 commit comments