-
Notifications
You must be signed in to change notification settings - Fork 0
/
find_unused_class.py
141 lines (101 loc) · 2.72 KB
/
find_unused_class.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!usr/bin/python
## -*- coding: UTF-8 -*-
#
#
#
import os
import sys
def findAllClass(file):
result = False
returnResult = []
for line in file.readlines():
if line.find("architecture armv7") != -1:
result = True
continue
if result:
contents = line.split(' ')
addressArray = []
if len(contents) > 1:
addressArray.extend(contents[1].split(' '))
for address in addressArray:
if address == '00000001':
continue
if address != '\n':
returnResult.append(address)
return returnResult
def findUsedClass(file):
result = False
returnResult = []
for line in file.readlines():
if line.find("architecture armv7") != -1:
result = True
continue
if result:
contents = line.split(' ')
addressArray = []
if len(contents) > 1:
addressArray.extend(contents[1].split(' '))
for address in addressArray:
if address == '00000001':
continue
if address == '00000000':
continue
if address != '\n':
returnResult.append(address)
return returnResult
def findClassNameByAddress(addressArray,file):
# file = open(addressMap,'r')
for address in addressArray:
file.seek(0)
find = False
for line in file.readlines():
if line.find(address) != -1:
find = True
continue
if find and line.find("name") != -1:
lineArray = line.split(' ')
if len(lineArray) > 0:
name = lineArray[len(lineArray) - 1].replace('\n','')
print "%s %s" %(address,name)
break
def checkAppBinary(argv):
if len(argv) < 2:
print '输入有效地址'
return False
path = argv[1]
if not os.path.isfile(path):
print '文件不存在'
return False
return True
def readAllClass(path):
file = os.popen('otool -v -s __DATA __objc_classlist %s' % (path))
return file
def readUsedClass(path):
file = os.popen('otool -v -s __DATA __objc_classrefs %s' % (path))
return file
def readClassName(path):
file = os.popen('otool -o %s' % (path))
content = file.read()
file.close()
fo = open('map.txt', "w")
fo.write(content)
fo.close()
return open(os.path.abspath('map.txt'))
if __name__ == '__main__':
if checkAppBinary(sys.argv):
path = sys.argv[1]
allClassFile = readAllClass(path)
allClass = findAllClass(allClassFile)
print 'All class size:%d' % (len(allClass))
usedClassFile = readUsedClass(path)
usedClass = findAllClass(usedClassFile)
print 'Used class size:%d' % (len(usedClass))
unUsedClass = list(set(allClass).difference(set(usedClass)))
print 'Unused class size:%d' % (len(unUsedClass))
if len(unUsedClass) > 0:
classNameFile = readClassName(path)
findClassNameByAddress(unUsedClass,classNameFile)
#Clean map file
mapPath = os.path.abspath('map.txt')
if os.path.isfile(mapPath):
os.remove(mapPath)