squash_ios_symbolicator 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ Squash iOS Symbolicator
2
+ =======================
3
+
4
+ This gem serves two purposes: to upload symbolication data to Squash, and to
5
+ notify Squash of new releases of the software (internally or externally).
6
+
7
+ This gem installs a `symbolicate` binary that converts a dSYM file into a format
8
+ usable for Squash, and then uploads the data to the Squash host. It also
9
+ installs a `squash_release` binary that notifies Squash of the release.
10
+
11
+ Documentation
12
+ -------------
13
+
14
+ Comprehensive documentation is written in YARD- and Markdown-formatted comments
15
+ throughout the source. To view this documentation as an HTML site, run
16
+ `rake doc`.
17
+
18
+ For an overview of the various components of Squash, see the website
19
+ documentation at https://github.com/SquareSquash/web.
20
+
21
+ Compatibility
22
+ -------------
23
+
24
+ This library is compatible with Ruby 1.8.6 and later, including Ruby Enterprise
25
+ Edition.
26
+
27
+ Requirements
28
+ ------------
29
+
30
+ This gem requires the `json` gem (http://rubygems.org/gems/json). You can use
31
+ any JSON gem that conforms to the typical standard
32
+ (`require 'json'; object.to_json`).
33
+
34
+ This gem uses the `plist` gem to parse your Info.plist file. The property list
35
+ must be in XML, not binary, format.
36
+
37
+ This gem uses `dwarfdump` to perform its symbolication. You'll therefore need
38
+ the Xcode Command Line tools installed on the machine that will be performing
39
+ the symbolication upload.
40
+
41
+ Usage
42
+ -----
43
+
44
+ ### Uploading Symbolication Data
45
+
46
+ This gem installs a command-line binary named `symbolicate`. It is called in the
47
+ following format:
48
+
49
+ ````
50
+ symbolicate [options]
51
+ ````
52
+
53
+ Example: `symbolicate --host https://squash.mycompany.com`
54
+
55
+ This binary is intended to be used as part of your release process. In Xcode,
56
+ you can add a build script that invokes this binary. Little configuration is
57
+ needed: Xcode sets a number of environment variables related to the build, and
58
+ `symbolicate` uses these by default to find the data it needs. You can customize
59
+ the script's options as needed to suit your specific toolchain, though.
60
+
61
+ An example "Run Script" phase for a build might look like this, assuming you had
62
+ the gem installed in a gemset using RVM:
63
+
64
+ ```` sh
65
+ /Users/someone/.rvm/bin/rvm 1.8.7@squash do /Users/someone/.rvm/gems/ruby-1.8.7-p370@squash/bin/symbolicate
66
+ ````
67
+
68
+ For documentation on `symbolicate`'s command-line options, run
69
+ `symbolicate --help.`
70
+
71
+ ### Release Notification
72
+
73
+ This gem installs a command-line binary named `squash_release`. It is called in
74
+ the following format:
75
+
76
+ ````
77
+ squash_release [options] <API key> <environment>
78
+ ````
79
+
80
+ Example: `squash_release --build 1138 a9232f94-6c2d-45ae-8f9e-9add5bd7ff35 internal_beta`
81
+
82
+ This binary is intended to be used as part of your release process, similar to
83
+ `symbolicate` (see above). Like `symbolicate`, sensible defaults are provided
84
+ for all command line switches.
85
+
86
+ For documentation on `squash_release`'s command-line options, run
87
+ `squash_release --help`.
88
+
89
+ Data Transmission
90
+ -----------------
91
+
92
+ Symbolication and release data is transmitted to Squash using JSON-over-HTTPS. A
93
+ default API endpoint is pre-configured, though you can always set your own (see
94
+ `symbolicate --help` or `squash_release --help`).
95
+
96
+ By default, `Net::HTTP` is used to transmit errors to the API server. If you
97
+ would prefer to use your own HTTP library, you can override the
98
+ {SquashUploader#http_post} method.
99
+
100
+ Use as a Library
101
+ ----------------
102
+
103
+ In addition to using the symbolication with Squash, you can also use the gem as
104
+ a library, to perform symbolication for your own purposes (even unrelated to
105
+ Squash). See the {Symbolicator} class documentation for more information. To
106
+ use the gem, include `require 'squash/symbolicator'` in your code.
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2012 Square Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'optparse'
18
+ require 'rubygems'
19
+ require 'squash/uploader'
20
+
21
+ def git_revision(dir)
22
+ head = File.read(File.join(dir, '.git', 'HEAD')).chomp
23
+ if head =~ /^ref: (.+)$/
24
+ File.read(File.join(dir, '.git', $1)).chomp
25
+ else
26
+ raise "Couldn't determine current revision from #{head.inspect}"
27
+ end
28
+ end
29
+
30
+ project_dir = Dir.getwd
31
+ revision = nil
32
+ options = {}
33
+
34
+ parser = OptionParser.new do |parser|
35
+ parser.banner = "Usage: squash_release [options] YOUR_SQUASH_HOST YOUR_API_KEY ENVIRONMENT BUILD_NUMBER"
36
+ parser.on('-o', '--open-timeout N', Integer, "HTTP connection open timeout") { |ot| options[:open_timeout] = ot }
37
+ parser.on('-r', '--read-timeout N', Integer, "HTTP connection data received timeout") { |rt| options[:read_timeout] = rt }
38
+ parser.on('-k', '--[no-]skip-verification', "Do not perform SSL peer verification") { |sv| options[:skip_verification] = sv }
39
+
40
+ parser.on('-p', '--project-dir F', "Specify a custom project directory (default current directory)") { |pd| project_dir = pd }
41
+ parser.on('-r', '--revision R', "Specify a code revision that was deployed (default current revision)") { |r| revision = r }
42
+
43
+ parser.on('-h', '--help', "Show this message") { puts parser; exit }
44
+ parser.on('--version', "Display version number of this program") { puts "1.0.0"; exit }
45
+ end
46
+ parser.parse!(ARGV)
47
+
48
+ if ARGV.size != 4
49
+ puts parser
50
+ exit 1
51
+ end
52
+
53
+ host = ARGV.shift
54
+ api_key = ARGV.shift
55
+ environment = ARGV.shift
56
+ build = ARGV.shift
57
+ revision = revision || git_revision(project_dir)
58
+
59
+ Squash::Uploader.new(host, options).transmit '/api/1.0/deploy.json',
60
+ {
61
+ 'project' => {'api_key' => api_key},
62
+ 'environment' => {'name' => environment},
63
+ 'deploy' => {
64
+ 'deployed_at' => Time.now,
65
+ 'revision' => revision,
66
+ 'build' => build
67
+ }
68
+ }
data/bin/symbolicate ADDED
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Copyright 2012 Square Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'optparse'
18
+ require 'base64'
19
+ require 'zlib'
20
+ require 'yaml'
21
+
22
+ require 'rubygems'
23
+ require 'squash/uploader'
24
+ require 'squash_ios_symbolicator'
25
+
26
+ def git_revision(dir)
27
+ head = File.read(File.join(dir, '.git', 'HEAD')).chomp
28
+ if head =~ /^ref: (.+)$/
29
+ File.read(File.join(dir, '.git', $1)).chomp
30
+ else
31
+ raise "Couldn't determine current revision from #{head.inspect}"
32
+ end
33
+ end
34
+
35
+ project_dir = ENV['PROJECT_DIR']
36
+ dsym_file = nil
37
+ options = {}
38
+
39
+ parser = OptionParser.new do |parser|
40
+ parser.banner = "Usage: symbolicate YOUR_API_HOST [options]"
41
+ parser.on('-o', '--open-timeout N', Integer, "HTTP connection open timeout") { |ot| options[:open_timeout] = ot }
42
+ parser.on('-r', '--read-timeout N', Integer, "HTTP connection data received timeout") { |rt| options[:read_timeout] = rt }
43
+ parser.on('-k', '--[no-]skip-verification', "Do not perform SSL peer verification") { |sv| options[:skip_verification] = sv }
44
+
45
+ parser.on('-d', '--dsym-file F', "Specify a custom dSYM file (default $DWARF_DSYM_FILE_NAME)") { |df| dsym_file = df }
46
+ parser.on('-p', '--project-dir F', "Specify a custom project directory (default $PROJECT_DIR)") { |pd| project_dir = pd }
47
+
48
+ parser.on('-h', '--help', "Show this message") { puts parser; exit }
49
+ parser.on('--version', "Display version number of this program") { puts "1.0.0"; exit }
50
+ end
51
+ parser.parse!(ARGV)
52
+
53
+ if ARGV.size != 1
54
+ puts parser
55
+ exit 1
56
+ end
57
+
58
+ host = ARGV.shift
59
+
60
+ if ENV['DWARF_DSYM_FOLDER_PATH'] && ENV['DWARF_DSYM_FILE_NAME']
61
+ dsym_file ||= File.join(ENV['DWARF_DSYM_FOLDER_PATH'], ENV['DWARF_DSYM_FILE_NAME'])
62
+ else
63
+ unless dsym_file
64
+ puts parser
65
+ exit 1
66
+ end
67
+ end
68
+
69
+ sym = Symbolicator.new(dsym_file, project_dir)
70
+ archs = sym.architectures
71
+ uuids = Hash.new
72
+ archs.each do |arch, uuid|
73
+ uuids[uuid] = [sym.symbols(arch), sym.lines(arch)]
74
+ end
75
+
76
+ Squash::Uploader.new(host, options).transmit '/api/1.0/symbolication.json',
77
+ 'symbolications' =>
78
+ uuids.map do |uuid, (symbols, lines)|
79
+ {
80
+ 'uuid' => uuid,
81
+ 'symbols' => Base64.encode64(Zlib::Deflate.deflate(symbols.to_yaml)),
82
+ 'lines' => Base64.encode64(Zlib::Deflate.deflate(lines.to_yaml))
83
+ }
84
+ end
@@ -0,0 +1,80 @@
1
+ # Copyright 2012 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # An address ranged mapped to a specific line of code, as part of a {Lines}
16
+ # aggregation. No symbol data is included.
17
+
18
+ Squash::Symbolicator::Line = Struct.new(:start_address, :file, :line, :column)
19
+
20
+ Squash::Symbolicator::Line.send(:define_method, :<=>) do |other|
21
+ raise ArgumentError unless other.kind_of?(Squash::Symbolicator::Line)
22
+ start_address <=> other.start_address
23
+ end
24
+
25
+ # An aggregation of the `Symbolicator::Line`s of a binary class. This class
26
+ # is enumerable.
27
+
28
+ class Squash::Symbolicator::Lines
29
+ include Enumerable
30
+
31
+ # Creates a new empty aggregation.
32
+
33
+ def initialize
34
+ @lines = Array.new
35
+ end
36
+
37
+ # Adds a line definition to the aggregation.
38
+ #
39
+ # @param [Fixnum] start_address The lowest program counter address
40
+ # corresponding to this method or function.
41
+ # @param [String] file The path to the file where this line is found.
42
+ # @param [Fixnum] lineno The line number in `file`.
43
+ # @param [Fixnum] col The column number in `file`.
44
+
45
+ def add(start_address, file, lineno, col)
46
+ index = @lines.find_index { |line| line.start_address > start_address }
47
+ new_line = Squash::Symbolicator::Line.new(start_address, file, lineno, col)
48
+
49
+ if index
50
+ @lines.insert index, new_line
51
+ else
52
+ @lines << new_line
53
+ end
54
+ end
55
+
56
+ # Returns the nearest `Symbolicator::Line` to a given program counter address.
57
+ #
58
+ # @param [Fixnum] address A program counter address.
59
+ # @return [Symbol, nil] The line corresponding to that address, or `nil` if
60
+ # the address is not symbolicated.
61
+
62
+ def for(address)
63
+ return @lines.last if @lines.last && @lines.last.start_address == address
64
+ idx = @lines.find_index { |line| address < line.start_address }
65
+ return nil unless idx
66
+ return @lines[idx - 1]
67
+ end
68
+
69
+ # Delegated to `Array`.
70
+ def each(*args) @lines.each(*args) end
71
+ # Delegated to `Array`.
72
+ def [](*args) @lines[*args] end
73
+ # Delegated to `Array`.
74
+ def clear(*args) @lines.clear(*args) end
75
+ # Delegated to `Array`.
76
+ def size(*args) @lines.size(*args) end
77
+
78
+ # @private
79
+ def inspect() "#<#{self.class} [#{size} lines]>" end
80
+ end
@@ -0,0 +1,87 @@
1
+ # Copyright 2012 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ # An address ranged mapped to a symbol (method or function name), as part of a
16
+ # {Symbols} aggregation. The file and line where the symbol is declared is also
17
+ # included.
18
+
19
+ Squash::Symbolicator::Symbol = Struct.new(:start_address, :end_address, :file, :line, :method)
20
+
21
+ Squash::Symbolicator::Symbol.send(:define_method, :<=>) do |other|
22
+ raise ArgumentError unless other.kind_of?(Squash::Symbolicator::Symbol)
23
+ if start_address == other.start_address
24
+ end_address <=> other.end_address
25
+ else
26
+ start_address <=> other.start_address
27
+ end
28
+ end
29
+
30
+ # An aggregation of the `Symbolicator::Symbol`s of a binary. This class is
31
+ # enumerable.
32
+
33
+ class Squash::Symbolicator::Symbols
34
+ include Enumerable
35
+
36
+ # Creates a new empty aggregation.
37
+
38
+ def initialize
39
+ @symbols = Array.new
40
+ end
41
+
42
+ # Adds a symbol definition to the aggregation.
43
+ #
44
+ # @param [Fixnum] start_address The lowest program counter address
45
+ # corresponding to this method or function.
46
+ # @param [Fixnum] end_address The highest program counter address
47
+ # corresponding to this method or function.
48
+ # @param [String] file The path to the file where this symbol is declared.
49
+ # @param [Fixnum] line The line number in `file` where this symbol is
50
+ # declared.
51
+ # @param [String] symbol The method or function name.
52
+
53
+ def add(start_address, end_address, file, line, symbol)
54
+ index = @symbols.find_index { |sym| sym.start_address > start_address || (sym.start_address == start_address && sym.end_address >= end_address) }
55
+ new_sym = Squash::Symbolicator::Symbol.new(start_address, end_address, file, line, symbol)
56
+
57
+ if index
58
+ @symbols.insert index, new_sym
59
+ else
60
+ @symbols << new_sym
61
+ end
62
+ end
63
+
64
+ # Returns the `Symbolicator::Symbol` containing a given program counter
65
+ # address. If there are symbols with overlapping address ranges, the one with
66
+ # the smallest range is returned.
67
+ #
68
+ # @param [Fixnum] address A program counter address.
69
+ # @return [Symbol, nil] The symbol corresponding to that address, or `nil` if
70
+ # the address is not symbolicated.
71
+
72
+ def for(address)
73
+ @symbols.detect { |sym| sym.start_address <= address && sym.end_address >= address }
74
+ end
75
+
76
+ # Delegated to `Array`.
77
+ def each(*args) @symbols.each(*args) end
78
+ # Delegated to `Array`.
79
+ def [](*args) @symbols[*args] end
80
+ # Delegated to `Array`.
81
+ def clear(*args) @symbols.clear(*args) end
82
+ # Delegated to `Array`.
83
+ def size(*args) @symbols.size(*args) end
84
+
85
+ # @private
86
+ def inspect() "#<#{self.class} [#{size} symbols]>" end
87
+ end
@@ -0,0 +1,141 @@
1
+ # Copyright 2012 Square Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'open3'
16
+
17
+ module Squash
18
+
19
+ # Uses `dwarfdump` to generate symbolication information for a given dSYM
20
+ # file. Uses `POpen3` to shell out to `dwarfdump`.
21
+
22
+ class Symbolicator
23
+
24
+ # Creates a new symbolicator for a given dSYM file.
25
+ #
26
+ # @param [String] dsym The path to a dSYM file (or DWARF file within).
27
+ # @param [String] project_dir The path to a project root that will be removed
28
+ # from file paths underneath that root.
29
+
30
+ def initialize(dsym, project_dir=nil)
31
+ @dsym = dsym
32
+ @project_dir = project_dir
33
+ end
34
+
35
+ # @return [Hash<String, String>] A hash mapping architectures (such as "i386")
36
+ # to the UUID for the symbolication of that architecture.
37
+
38
+ def architectures
39
+ architectures = Hash.new
40
+
41
+ stdin, stdout, stderr = Open3.popen3('dwarfdump', '-u', @dsym)
42
+ stdout.each_line do |line|
43
+ if line =~ /^UUID: ([0-9A-F\-]+) \((.+?)\) [^\s]+$/
44
+ architectures[$2] = $1
45
+ end
46
+ end
47
+
48
+ return architectures
49
+ end
50
+
51
+ # Extracts symbol information from the dSYM.
52
+ #
53
+ # @param [String] arch The architecture to extract symbols for.
54
+ # @return [Symbols] The symbols defined in the dSYM.
55
+ # @see #architectures
56
+
57
+ def symbols(arch)
58
+ symbolications = Symbols.new
59
+ current_subprogram = nil
60
+
61
+ stdin, stdout, stderr = Open3.popen3('dwarfdump', '--debug-info', "--arch=#{arch}", @dsym)
62
+ stdout.each_line do |line|
63
+ if current_subprogram
64
+ if line =~ /^\s*AT_(\w+)\(\s*(.+?)\s*\)$/
65
+ tag = $1
66
+ value = $2
67
+
68
+ case tag
69
+ when 'name', 'decl_file' # quoted strings
70
+ value = value[1..-2]
71
+ when 'decl_line' # decimal integers
72
+ value = value.to_i
73
+ when 'prototyped', 'external' # booleans
74
+ value = (value == '0x01')
75
+ when 'low_pc', 'high_pc' # hex integers
76
+ value = value.hex
77
+ end
78
+
79
+ current_subprogram[tag] = value
80
+ elsif line =~ /^0x[0-9a-f]+:\s+TAG_(\w+)/
81
+ current_subprogram['decl_file'].sub!(/^#{Regexp.escape @project_dir}\//, '') if @project_dir
82
+ symbolications.add current_subprogram['low_pc'],
83
+ current_subprogram['high_pc'],
84
+ current_subprogram['decl_file'],
85
+ current_subprogram['decl_line'],
86
+ current_subprogram['name']
87
+
88
+ current_subprogram = ($1 == 'subprogram') ? Hash.new : nil
89
+ end
90
+ else
91
+ if line =~ /^0x[0-9a-f]+:\s+TAG_subprogram\s+\[\d+\]\s+\*$/
92
+ current_subprogram = Hash.new
93
+ end
94
+ end
95
+ end
96
+
97
+ return symbolications
98
+ end
99
+
100
+ # Extracts line number information from the dSYM.
101
+ #
102
+ # @param [String] arch The architecture to extract symbols for.
103
+ # @return [Symbols] The line info defined in the dSYM.
104
+ # @see #architectures
105
+
106
+ def lines(arch)
107
+ lines = Lines.new
108
+ current_line = nil
109
+
110
+ stdin, stdout, stderr = Open3.popen3('dwarfdump', '--debug-line', "--arch=#{arch}", @dsym)
111
+ stdout.each_line do |line|
112
+ if current_line
113
+ if line =~ /^include_directories\[\s+(\d+)\] = '(.+)'$/
114
+ current_line[:include_directories][$1] = $2
115
+ elsif line =~ /^file_names\[\s*(\d+)\]\s+(\d+)\s+0x[0-9a-f]+\s+0x[0-9a-f]+\s+(.+)$/
116
+ current_line[:file_names][$1] = current_line[:include_directories][$2] + '/' + $3
117
+ elsif line =~ /^ (0x[0-9a-f]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+/
118
+ path = current_line[:file_names][$2]
119
+ line = $3.to_i
120
+ col = $4.to_i
121
+ start_address = $1.hex
122
+ path.sub!(/^#{Regexp.escape @project_dir}\//, '') if @project_dir
123
+ lines.add start_address, path, line, col
124
+ end
125
+ else
126
+ if line =~ /^debug_line\[0x[0-9a-f]+\]$/
127
+ current_line = {
128
+ :include_directories => {},
129
+ :file_names => {}
130
+ }
131
+ end
132
+ end
133
+ end
134
+
135
+ return lines
136
+ end
137
+ end
138
+ end
139
+
140
+ require 'squash/symbolicator/lines'
141
+ require 'squash/symbolicator/symbols'
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: squash_ios_symbolicator
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Tim Morgan
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-12-07 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ hash: 3
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ name: plist
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ hash: 3
42
+ segments:
43
+ - 0
44
+ version: "0"
45
+ type: :runtime
46
+ name: squash_uploader
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ prerelease: false
50
+ requirement: &id003 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ hash: 3
56
+ segments:
57
+ - 0
58
+ version: "0"
59
+ type: :development
60
+ name: rspec
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :development
74
+ name: yard
75
+ version_requirements: *id004
76
+ - !ruby/object:Gem::Dependency
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ type: :development
88
+ name: redcarpet
89
+ version_requirements: *id005
90
+ - !ruby/object:Gem::Dependency
91
+ prerelease: false
92
+ requirement: &id006 !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ type: :development
102
+ name: jeweler
103
+ version_requirements: *id006
104
+ description: This gem includes a library that imports dwarfdump symbolications, and a binary that uploads the data to Squash.
105
+ email: tim@squareup.com
106
+ executables:
107
+ - symbolicate
108
+ - squash_release
109
+ extensions: []
110
+
111
+ extra_rdoc_files:
112
+ - LICENSE.txt
113
+ - README.md
114
+ files:
115
+ - LICENSE.txt
116
+ - README.md
117
+ - bin/squash_release
118
+ - bin/symbolicate
119
+ - lib/squash/symbolicator.rb
120
+ - lib/squash/symbolicator/lines.rb
121
+ - lib/squash/symbolicator/symbols.rb
122
+ homepage: http://github.com/SquareSquash/ios_symbolicator
123
+ licenses:
124
+ - Apache 2.0
125
+ post_install_message:
126
+ rdoc_options: []
127
+
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ">="
134
+ - !ruby/object:Gem::Version
135
+ hash: 3
136
+ segments:
137
+ - 0
138
+ version: "0"
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ none: false
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ hash: 3
145
+ segments:
146
+ - 0
147
+ version: "0"
148
+ requirements: []
149
+
150
+ rubyforge_project:
151
+ rubygems_version: 1.8.24
152
+ signing_key:
153
+ specification_version: 3
154
+ summary: Binary and library for symbolicating your iOS project and uploading the symbolication to Squash.
155
+ test_files: []
156
+