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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 52577b6f2c97038240b05a5212212a3668c9c645
4
- data.tar.gz: 5acbb09d6105ca83464b9bae3b5a55d5f54a60bd
3
+ metadata.gz: 5012e8dfb8b05a8cb6bfb0823d55e168a35d0e13
4
+ data.tar.gz: 3e83c424c270cf096c27f1202f6cf8eb211c952d
5
5
  SHA512:
6
- metadata.gz: 53f679d4ee619c2cde661629853696c273e36c346116793a5633debb17422361ec547c430c1fa105ba0faa2d407b2ab418ddffb041607750f6c0cfd4aada217a
7
- data.tar.gz: 03c36b0db44c69ff7ba2bd6cf6074aa43d0a64f96e785768cbb429c2426250582cecb7ee4deed5d38c7979b3453c0321cc2cf4aa15f4a8da5d8c1cb72ea74ecf
6
+ metadata.gz: c9bb7e04fdb82596c7ba9e83a729d6e7cb1746a9f560b2eeb9e4d7221937c6be6254de6a2d4c53fa49d2ea5af94dd7dc10aed5ca18230817bd698343b6bd4c75
7
+ data.tar.gz: 09621dea0dafcc7b6b7f2aff9d8406a331df7c786fb8235a0fe65124ab0b9e32ac0c98028388d2ba35131900cb0fd77395dba762d26371855cfc5e8d06385061
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  .DS_Store
2
2
 
3
+ .idea/
3
4
  /.bundle/
4
5
  /.yardoc
5
6
  /Gemfile.lock
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
 
@@ -1,3 +1,3 @@
1
1
  module LinkmapIos
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
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.include? "#"
67
- if line.include? "# Object files:"
76
+ if line.start_with? "#"
77
+ if line.start_with? "# Object files:"
68
78
  @subparser = :parse_object_files
69
- elsif line.include? "# Sections:"
79
+ elsif line.start_with? "# Sections:"
70
80
  @subparser = :parse_sections
71
- elsif line.include? "# Symbols:"
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
- lib = $2.end_with?('.tbd') ? 'System' : 'Main'
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
- # Do nothing
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 =~ /.*(0x.*)\s\[(.*\d)\].*/
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[:size] = (id_info[:size] or 0) + $1.to_i(16)
126
- @library_map[id_info[:library]].size += $1.to_i(16)
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 = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
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.0
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: 2016-08-10 00:00:00.000000000 Z
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.2.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