├── Find Block Symbol.py ├── README.md └── restore-symbol /Find Block Symbol.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | 4 | finalSymbols = [] 5 | 6 | 7 | fpath = Document.askFile( "Select path to save json file", "block_sym.json", 'save' ) 8 | print "select f path ", fpath 9 | 10 | doc = Document.getCurrentDocument() 11 | IS32BIT = not doc.is64Bits() 12 | 13 | def searchBlockReference(segment, baseAddr, callfuncName = "NoFunc"): 14 | print "base addr 0x%x" % baseAddr 15 | for x in xrange(baseAddr - 24,baseAddr + 24, 2): 16 | # the addr which point to maybe a block 17 | r = segment.getReferencesFromAddress( x ) 18 | # print "ref from ", hex( x ) 19 | for addr in r: 20 | refSeg = doc.getSegmentAtAddress( addr ) 21 | proc = refSeg.getProcedureAtAddress( addr ) 22 | 23 | if proc: 24 | startAddr = proc.getEntryPoint() 25 | name = refSeg.getNameAtAddress( startAddr ) 26 | if IS32BIT: 27 | if name.find("sub") != -1: 28 | return True, startAddr, callfuncName + "_block_invoke" 29 | else: 30 | if name and name.find("block_invoke") != -1: 31 | print "find ", hex( startAddr ) 32 | return True, startAddr, name 33 | else: 34 | segmentName, sectionName = getSegmentAndSection( addr ) 35 | name = "" 36 | if segmentName == "__TEXT" and sectionName == "__text" : 37 | # it`s in code section, make the function name as block_invoke prefix immediately 38 | name = callfuncName + "_block_invoke" 39 | 40 | if name and name.find("block_invoke") != -1: 41 | print "find ", hex( addr ) 42 | return True, addr, name 43 | 44 | return False,0,0 45 | 46 | def getSegmentAndSection( addr ): 47 | seg = doc.getSegmentAtAddress(addr) 48 | sectionList = seg.getSectionsList() 49 | for sec in sectionList: 50 | if addr > sec.getStartingAddress() and \ 51 | addr < (sec.getStartingAddress() + sec.getLength() ): 52 | return seg.getName(), sec.getName() 53 | return seg.getName(), "" 54 | 55 | # 1.Stack Block Scan 56 | 57 | stackBlockAddr = doc.getAddressForName( "__NSConcreteStackBlock" ) 58 | print "stack block symbol addr", hex(stackBlockAddr) 59 | 60 | # External Symbols Segment 61 | sbInSegment = doc.getSegmentAtAddress(stackBlockAddr) 62 | refsToSB = sbInSegment.getReferencesOfAddress(stackBlockAddr) 63 | 64 | refsToSBAddr = [] 65 | for addr in refsToSB: 66 | seg = doc.getSegmentAtAddress(addr) 67 | if seg.getName() == "__DATA": 68 | refsToSBAddr = seg.getReferencesOfAddress(addr) 69 | break 70 | 71 | if len(refsToSBAddr) > 0: 72 | # refs 73 | for i in xrange(0,len(refsToSBAddr)): 74 | addr = refsToSBAddr[i] 75 | if IS32BIT: 76 | if i <= len(refsToSBAddr)-2: 77 | print "%x - %x" % (refsToSBAddr[i+1], addr) 78 | if refsToSBAddr[i+1] - addr <= 12: 79 | # 32bit armv7 has multip address in a same reference 80 | print "continue" 81 | continue 82 | else: 83 | addr = refsToSBAddr[i] 84 | 85 | print "fn %x" % addr 86 | seg = doc.getSegmentAtAddress(addr) 87 | proc = seg.getProcedureAtAddress( addr ) 88 | if proc: 89 | procName = seg.getNameAtAddress( proc.getEntryPoint() ) 90 | 91 | ret, funcAddr, blockName = searchBlockReference(seg, addr, procName) 92 | if ret: 93 | print "name: %s" % blockName 94 | print 'address: "0x%x"' % funcAddr 95 | finalSymbols.append( { "name": blockName, "address": ("0x%x" % funcAddr) } ) 96 | else: 97 | print "can`t find stack block define!!" 98 | 99 | 100 | # 2.Global Block Scan 101 | 102 | globalBlockAddr = doc.getAddressForName( "__NSConcreteGlobalBlock" ) 103 | print "==== global block addr", hex( globalBlockAddr ) 104 | gbInSegment = doc.getSegmentAtAddress(globalBlockAddr) 105 | print "ref segment ", gbInSegment.getName() 106 | # doc.log( "segment %s" % doc.getSegmentAtAddress(globalBlockAddr) ) 107 | refsToGBSymbol = gbInSegment.getReferencesOfAddress( globalBlockAddr ) 108 | for gbRef in refsToGBSymbol: 109 | print "global block addr 0x%x" % (gbRef) 110 | seg = doc.getSegmentAtAddress( gbRef ) 111 | funcPointOffset = 12 if IS32BIT else 16 112 | funcPointAddr = gbRef + funcPointOffset 113 | print "func point addr 0x%x" % funcPointAddr 114 | refsFromFuncPoint = seg.getReferencesFromAddress( funcPointAddr ) 115 | for funcStartAddr in refsFromFuncPoint: 116 | print "block func start addr 0x%x" % funcStartAddr 117 | funcSeg = doc.getSegmentAtAddress( funcStartAddr ) 118 | proc = funcSeg.getProcedureAtAddress( funcStartAddr ) 119 | if proc: 120 | funcStartAddr = proc.getEntryPoint() 121 | name = funcSeg.getNameAtAddress( funcStartAddr ) 122 | else: 123 | print "!! is not procedure 0x%x" % funcStartAddr 124 | name = funcSeg.getNameAtAddress( funcStartAddr ) 125 | 126 | # if hopper does not parse function which call the block 127 | # then we search who reference the globalBlock define 128 | if not name: 129 | continue 130 | if name.find("block_invoke") == -1: 131 | refsToGlobalBlockDef = seg.getReferencesOfAddress( gbRef ) 132 | for funcAddr in refsToGlobalBlockDef: 133 | funcSeg = doc.getSegmentAtAddress( funcAddr ) 134 | proc = funcSeg.getProcedureAtAddress( funcAddr ) 135 | if proc: 136 | startAddr = proc.getEntryPoint() 137 | name = funcSeg.getNameAtAddress( startAddr ) + "_block_invoke" 138 | else: 139 | print "!!! ERROR is not proc ", hex( funcAddr ) 140 | # print "Instruction 0x%x" % funcSeg.instructionStart( funcAddr ) 141 | name = funcSeg.getNameAtAddress( funcAddr ) + "_block_invoke" 142 | print "name: %s" % name 143 | print "address: 0x%x" % funcStartAddr 144 | finalSymbols.append( { "name": ("%s" % name), "address": ("0x%x" % funcStartAddr) } ) 145 | 146 | jsonDump = json.dumps( finalSymbols ) 147 | # print jsonDump 148 | f = open( fpath, "w" ) 149 | f.write( jsonDump ) 150 | f.close() 151 | 152 | 153 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # parse-crash-log 2 | symbolicate crash log with out dSYM file 3 | 4 | Find Block Symbol.py is a python script for Hopper, this script could find block procedure address in mach-o and then generate a json file that should be used to restore block symbols. 5 | -------------------------------------------------------------------------------- /restore-symbol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/troyzhao/parse-crash-log/b71ab36ad4bdf033cc608e9b51930dc3bc58cd71/restore-symbol --------------------------------------------------------------------------------