linkmap_ios 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +5 -1
- data/lib/linkmap_ios/version.rb +1 -1
- data/lib/linkmap_ios.rb +78 -18
- data/linkmap_ios.gemspec +1 -1
- metadata +3 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5012e8dfb8b05a8cb6bfb0823d55e168a35d0e13
|
4
|
+
data.tar.gz: 3e83c424c270cf096c27f1202f6cf8eb211c952d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9bb7e04fdb82596c7ba9e83a729d6e7cb1746a9f560b2eeb9e4d7221937c6be6254de6a2d4c53fa49d2ea5af94dd7dc10aed5ca18230817bd698343b6bd4c75
|
7
|
+
data.tar.gz: 09621dea0dafcc7b6b7f2aff9d8406a331df7c786fb8235a0fe65124ab0b9e32ac0c98028388d2ba35131900cb0fd77395dba762d26371855cfc5e8d06385061
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -34,10 +34,14 @@ Byte is the default unit in all kind of output.
|
|
34
34
|
## Release Note
|
35
35
|
### [0.1.0] 2016-08-09
|
36
36
|
1. Finish all base functions
|
37
|
+
### [0.1.1] 2017-3-29
|
38
|
+
1. Increase the concurrency, add dead stripped symbol handle in symbol analyze
|
39
|
+
2. Add simple section analyze
|
40
|
+
3. Add uncounted section number in report
|
37
41
|
|
38
42
|
## TODO
|
39
43
|
1. Add test specs
|
40
|
-
2. Add sections analysis
|
44
|
+
2. Add full sections analysis function
|
41
45
|
|
42
46
|
## Development
|
43
47
|
|
data/lib/linkmap_ios/version.rb
CHANGED
data/lib/linkmap_ios.rb
CHANGED
@@ -3,7 +3,7 @@ require "filesize"
|
|
3
3
|
require "json"
|
4
4
|
|
5
5
|
module LinkmapIos
|
6
|
-
Library = Struct.new(:name, :size, :objects)
|
6
|
+
Library = Struct.new(:name, :size, :objects, :dead_symbol_size)
|
7
7
|
|
8
8
|
class LinkmapParser
|
9
9
|
attr_reader :id_map
|
@@ -13,6 +13,7 @@ module LinkmapIos
|
|
13
13
|
@file_path = file_path
|
14
14
|
@id_map = {}
|
15
15
|
@library_map = {}
|
16
|
+
@section_map = {}
|
16
17
|
end
|
17
18
|
|
18
19
|
def hash
|
@@ -22,12 +23,13 @@ module LinkmapIos
|
|
22
23
|
parse
|
23
24
|
|
24
25
|
total_size = @library_map.values.map(&:size).inject(:+)
|
25
|
-
detail = @library_map.values.map { |lib| {:library => lib.name, :size => lib.size, :objects => lib.objects.map { |o| @id_map[o][:object] }}}
|
26
|
+
detail = @library_map.values.map { |lib| {:library => lib.name, :size => lib.size, :dead_symbol_size => lib.dead_symbol_size, :objects => lib.objects.map { |o| @id_map[o][:object] }}}
|
27
|
+
total_dead_size = @library_map.values.map(&:dead_symbol_size).inject(:+)
|
26
28
|
|
27
29
|
# puts total_size
|
28
30
|
# puts detail
|
29
31
|
|
30
|
-
@result_hash = {:total => total_size, :detail => detail}
|
32
|
+
@result_hash = {:total => total_size, :detail => detail, :total_dead => total_dead_size}
|
31
33
|
@result_hash
|
32
34
|
end
|
33
35
|
|
@@ -40,6 +42,8 @@ module LinkmapIos
|
|
40
42
|
|
41
43
|
report = "# Total size\n"
|
42
44
|
report << "#{Filesize.from(result[:total].to_s + 'B').pretty}\n"
|
45
|
+
report << "# Dead Size\n"
|
46
|
+
report << "#{Filesize.from(result[:total_dead].to_s + 'B').pretty}\n"
|
43
47
|
report << "\n# Library detail\n"
|
44
48
|
result[:detail].sort_by { |h| h[:size] }.reverse.each do |lib|
|
45
49
|
report << "#{lib[:library]} #{Filesize.from(lib[:size].to_s + 'B').pretty}\n"
|
@@ -49,6 +53,13 @@ module LinkmapIos
|
|
49
53
|
report << "#{id_info[:object]} #{Filesize.from(id_info[:size].to_s + 'B').pretty}\n"
|
50
54
|
end
|
51
55
|
|
56
|
+
report << "# Uncounted Section Detail"
|
57
|
+
@section_map.select do |_, value|
|
58
|
+
value[:residual_size] != 0
|
59
|
+
end
|
60
|
+
.each do |seg_sec_name, value|
|
61
|
+
report << "\n#{seg_sec_name}, start_address: #{value[:start_address]}, end_address: #{value[:end_address]}, residual_size: #{value[:residual_size]}"
|
62
|
+
end
|
52
63
|
report
|
53
64
|
end
|
54
65
|
|
@@ -60,16 +71,17 @@ module LinkmapIos
|
|
60
71
|
# Deal with string like
|
61
72
|
unless line.valid_encoding?
|
62
73
|
line = line.encode("UTF-16", :invalid => :replace, :replace => "?").encode('UTF-8')
|
63
|
-
# puts "#{line_num}: #{line}"
|
64
74
|
end
|
65
75
|
|
66
|
-
if line.
|
67
|
-
if line.
|
76
|
+
if line.start_with? "#"
|
77
|
+
if line.start_with? "# Object files:"
|
68
78
|
@subparser = :parse_object_files
|
69
|
-
elsif line.
|
79
|
+
elsif line.start_with? "# Sections:"
|
70
80
|
@subparser = :parse_sections
|
71
|
-
elsif line.
|
81
|
+
elsif line.start_with? "# Symbols:"
|
72
82
|
@subparser = :parse_symbols
|
83
|
+
elsif line.start_with? '# Dead Stripped Symbols:'
|
84
|
+
@subparser = :parse_dead
|
73
85
|
end
|
74
86
|
else
|
75
87
|
send(@subparser, line)
|
@@ -80,9 +92,7 @@ module LinkmapIos
|
|
80
92
|
raise e
|
81
93
|
end
|
82
94
|
end
|
83
|
-
|
84
|
-
# puts @id_map
|
85
|
-
# puts @library_map
|
95
|
+
puts "There are #{@section_map.values.map{|value| value[:residual_size]}.inject(:+)} Byte in some section can not be analyze"
|
86
96
|
end
|
87
97
|
|
88
98
|
def parse_object_files(text)
|
@@ -93,7 +103,7 @@ module LinkmapIos
|
|
93
103
|
id = $1.to_i
|
94
104
|
@id_map[id] = {:library => $2, :object => $3}
|
95
105
|
|
96
|
-
library = (@library_map[$2] or Library.new($2, 0, []))
|
106
|
+
library = (@library_map[$2] or Library.new($2, 0, [], 0))
|
97
107
|
library.objects << id
|
98
108
|
@library_map[$2] = library
|
99
109
|
elsif text =~ /\[(.*)\].*\/(.*)/
|
@@ -102,30 +112,80 @@ module LinkmapIos
|
|
102
112
|
# [100] /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks//UIKit.framework/UIKit.tbd
|
103
113
|
# Main
|
104
114
|
# [ 3] /SomePath/Release-iphoneos/CrashDemo.build/Objects-normal/arm64/AppDelegate.o
|
115
|
+
# Dynamic Framework
|
116
|
+
# [9742] /SomePath/Pods/AFNetworking/Classes/AFNetworking.framework/AFNetworking
|
105
117
|
id = $1.to_i
|
106
|
-
|
118
|
+
if text.include?('.framework') and not $2.include?('.')
|
119
|
+
lib = $2
|
120
|
+
else
|
121
|
+
lib = $2.end_with?('.tbd') ? 'System' : 'Main'
|
122
|
+
end
|
107
123
|
@id_map[id] = {:library => lib, :object => $2}
|
108
124
|
|
109
|
-
library = (@library_map[lib] or Library.new(lib, 0, []))
|
125
|
+
library = (@library_map[lib] or Library.new(lib, 0, [], 0))
|
110
126
|
library.objects << id
|
111
127
|
@library_map[lib] = library
|
128
|
+
elsif text =~ /\[(.*)\]\s*([\w\s]+)/
|
129
|
+
# Sample:
|
130
|
+
# [ 0] linker synthesized
|
131
|
+
# [ 1] dtrace
|
132
|
+
id = $1.to_i
|
133
|
+
@id_map[id] = {library: 'Main', object: $2}
|
112
134
|
end
|
113
135
|
end
|
114
136
|
|
115
137
|
def parse_sections(text)
|
116
|
-
#
|
138
|
+
# Sample:
|
139
|
+
# 0x100005F00 0x031B6A98 __TEXT __tex
|
140
|
+
text_array = text.split(' ').each(&:strip)
|
141
|
+
section_name = text_array[3]
|
142
|
+
segment_name = text_array[2]
|
143
|
+
start_address = text_array.first.to_i(16)
|
144
|
+
end_address = start_address + text_array[1].to_i(16)
|
145
|
+
# section name may be dulicate in different segment
|
146
|
+
seg_sec_name = "#{segment_name}#{section_name}"
|
147
|
+
@section_map[seg_sec_name.to_sym] = {
|
148
|
+
segment_name: segment_name,
|
149
|
+
section_name: section_name,
|
150
|
+
start_address: start_address,
|
151
|
+
end_address: end_address,
|
152
|
+
symbol_size: 0,
|
153
|
+
residual_size: text_array[1].to_i(16)
|
154
|
+
}
|
117
155
|
end
|
118
156
|
|
119
157
|
def parse_symbols(text)
|
120
158
|
# Sample
|
121
159
|
# 0x1000055C8 0x0000003C [ 4] -[FirstViewController viewWillAppear:]
|
122
|
-
if text =~
|
160
|
+
if text =~ /^0x(.+?)\s+0x(.+?)\s+\[(.+?)\]/
|
161
|
+
symbol_address = $1.to_i(16)
|
162
|
+
symbol_size = $2.to_i(16)
|
163
|
+
symbol_file_id = $3.to_i
|
164
|
+
id_info = @id_map[symbol_file_id]
|
165
|
+
if id_info
|
166
|
+
id_info[:size] = (id_info[:size] or 0) + symbol_size
|
167
|
+
@library_map[id_info[:library]].size += symbol_size
|
168
|
+
seg_sec_name = @section_map.detect {|seg_sec_name, value| (value[:start_address]...value[:end_address]).include? symbol_address}[0]
|
169
|
+
@section_map[seg_sec_name.to_sym][:symbol_size] += symbol_size
|
170
|
+
@section_map[seg_sec_name.to_sym][:residual_size] -= symbol_size
|
171
|
+
else
|
172
|
+
puts "#{text.inspect} can not found object file"
|
173
|
+
end
|
174
|
+
else
|
175
|
+
puts "#{text.inspect} can not match symbol regular"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def parse_dead(text)
|
180
|
+
# <<dead>> 0x00000008 [ 3] literal string: v16@0:8
|
181
|
+
if text =~ /^<<dead>>\s+0x(.+?)\s+\[(.+?)\]\w*/
|
123
182
|
id_info = @id_map[$2.to_i]
|
124
183
|
if id_info
|
125
|
-
id_info[:
|
126
|
-
@library_map[id_info[:library]].
|
184
|
+
id_info[:dead_symbol_size] = (id_info[:dead_symbol_size] or 0) + $1.to_i(16)
|
185
|
+
@library_map[id_info[:library]].dead_symbol_size += $1.to_i(16)
|
127
186
|
end
|
128
187
|
end
|
129
188
|
end
|
189
|
+
|
130
190
|
end
|
131
191
|
end
|
data/linkmap_ios.gemspec
CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
|
28
28
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
29
29
|
spec.bindir = "bin"
|
30
|
-
spec.executables =
|
30
|
+
spec.executables = ["linkmap_ios"]
|
31
31
|
spec.require_paths = ["lib"]
|
32
32
|
|
33
33
|
spec.add_dependency "thor", "~> 0.19.1"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: linkmap_ios
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Luo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -86,9 +86,7 @@ description: "A ruby library to parse linkmap file generated by Xcode.\n
|
|
86
86
|
email:
|
87
87
|
- radishchrist@gmail.com
|
88
88
|
executables:
|
89
|
-
- console
|
90
89
|
- linkmap_ios
|
91
|
-
- setup
|
92
90
|
extensions: []
|
93
91
|
extra_rdoc_files: []
|
94
92
|
files:
|
@@ -125,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
123
|
version: '0'
|
126
124
|
requirements: []
|
127
125
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
126
|
+
rubygems_version: 2.4.8
|
129
127
|
signing_key:
|
130
128
|
specification_version: 4
|
131
129
|
summary: A ruby library to parse linkmap file generated by Xcode
|