symsym 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (11) hide show
  1. data/.document +5 -0
  2. data/Gemfile +10 -0
  3. data/Gemfile.lock +15 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.md +42 -0
  6. data/README.rdoc +25 -0
  7. data/Rakefile +39 -0
  8. data/VERSION +1 -0
  9. data/bin/symsym +63 -0
  10. data/lib/symsym.rb +150 -0
  11. metadata +93 -0
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "jeweler", "~> 1.6.0"
10
+ end
@@ -0,0 +1,15 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.0)
6
+ bundler (~> 1.0.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.8.7)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ jeweler (~> 1.6.0)
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ulrich Zurucker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # symsym Crashreport Desymbolizer for Mac OS X
2
+
3
+ symsym is a tool for Mac OS X that allows to de-symbolize crashlogs.
4
+
5
+ ### Install
6
+
7
+ sudo gem install symsym
8
+
9
+ ## Usage
10
+
11
+ symsym will look for a dSYM bundle that matches the bundle identifier, version and short version string found in the crashreport. It will run gdb to desymbolize the addresses in the given crashlog.
12
+ The crashlog can be read from a file or from the Mac OS X pasteboard.
13
+ Output can be to a file, the OS X pasteboard or stdout
14
+
15
+ Use symsym from the command line:
16
+
17
+ * -i read crashreport from given file
18
+ * -o write de-symbolized crashreport to given file
19
+ * -p read crashreport from pasteboard
20
+ * -c write de-symbolized crashreport to pasteboard
21
+ * -d The path where symsym will look for a matching .dSYM bundle - and of course in all subfolders of this path
22
+
23
+ So when you want to replace the crashreport in your pasteboard with the de-symbolized version, go to a directory that contains your dSYM bundles, type
24
+
25
+ symsym -p -c
26
+
27
+ and you are done!
28
+
29
+ _Note:_ gdb needs the application bundle next to the dSYM bundle to be able to desymbolize the crashlog.
30
+
31
+ ## Issues/TODO
32
+
33
+ * Read the architecture from the crashreport
34
+
35
+ ## Contribute
36
+
37
+ * fork me on Github - [https://github.com/sononum/symsym](https://github.com/sononum/symsym)
38
+ * send a pull request
39
+
40
+ ## Copyright
41
+
42
+ Copyright (c) 2011 Ulrich Zurucker. See LICENSE.txt for further details.
@@ -0,0 +1,25 @@
1
+ = symsym
2
+
3
+ symsym is a tool for Mac OS X that allows to de-symbolize crashlogs.
4
+
5
+ === Usage
6
+ symsym will look for a dSYM bundle that matches the bundle identifier, version and short version string found in the crashreport. It will run gdb to desymbolize the addresses in the given crashlog.
7
+ The crashlog can be read from a file or from the Mac OS X pasteboard.
8
+ Output can be to a file, the OS X pasteboard or stdout
9
+
10
+ Use symsym from the command line:
11
+ -i read crashreport from given file
12
+ -o write de-symbolized crashreport to given file
13
+ -p read crashreport from pasteboard
14
+ -c write de-symbolized crashreport to pasteboard
15
+ -d The path where symsym will look for a matching .dSYM bundle - and of course in all subfolders of this path
16
+
17
+ == Issues/TODO
18
+
19
+ * Read the architecture from the crashreport
20
+
21
+ == Copyright
22
+
23
+ Copyright (c) 2011 Ulrich Zurucker. See LICENSE.txt for
24
+ further details.
25
+
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "symsym"
18
+ gem.homepage = "http://github.com/sononum/symsym"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Crashlog symbolizer for Mac OS X}
21
+ gem.description = %Q{symsym can be used to symbolize crashlogs from dSYM files}
22
+ gem.email = "ulizurucker@googlemail.com"
23
+ gem.authors = ["Ulrich Zurucker"]
24
+ gem.executables = ["symsym"]
25
+ gem.default_executable = 'symsym'
26
+ # dependencies defined in Gemfile
27
+ end
28
+ Jeweler::RubygemsDotOrgTasks.new
29
+
30
+
31
+ require 'rake/rdoctask'
32
+ Rake::RDocTask.new do |rdoc|
33
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
34
+
35
+ rdoc.rdoc_dir = 'rdoc'
36
+ rdoc.title = "symsym #{version}"
37
+ rdoc.rdoc_files.include('README*')
38
+ rdoc.rdoc_files.include('lib/**/*.rb')
39
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.0
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
4
+
5
+ require 'optparse'
6
+ require 'symsym'
7
+
8
+ dsymsearchpath = nil
9
+
10
+ options = {}
11
+ options[:dsymsearchpath] = "."
12
+ options[:reportfile] = nil
13
+ options[:copypasteboard] = false
14
+ options[:outputfile] = nil
15
+ report = nil
16
+
17
+ optparse = OptionParser.new do|opts|
18
+ opts.on('-h', '--help', 'Display this screen' ) do
19
+ puts opts
20
+ exit
21
+ end
22
+ opts.on('-i FILE', "Read crashlog from FILE" ) do |p|
23
+ options[:reportfile] = p
24
+ end
25
+ opts.on('-o FILE', "Write symbolized crashlog to FILE") do |p|
26
+ options[:outputfile] = p
27
+ end
28
+ opts.on('-d FILE', "dSYM Search Path - the path where symsym should look for a matching dSYM bundle. If not given, look in ." ) do |p|
29
+ options[:dsymsearchpath] = p
30
+ end
31
+ opts.on('-p', '--pasteboard', "Use pasteboard content as report input") do
32
+ report = `pbpaste`
33
+ end
34
+ opts.on('-c', '--copypasteboard', "Copy the symbolized crashlog to pasteboard") do
35
+ options[:copypasteboard] = true
36
+ end
37
+ end
38
+
39
+ optparse.parse!
40
+
41
+ unless report
42
+ reportfile = options[:reportfile]
43
+ if reportfile && File.exist?(reportfile)
44
+ report = File.new(reportfile).read
45
+ else
46
+ puts "No input crashlog given. Use --help for usage."
47
+ end
48
+ end
49
+
50
+ exit(1) unless report
51
+
52
+ report = Crashreport.new(report, options[:dsymsearchpath])
53
+ report.symbolicate!
54
+
55
+ if (options[:copypasteboard])
56
+ IO.popen('pbcopy', 'r+').puts report.report
57
+ end
58
+
59
+ if (options[:outputfile])
60
+ File.new(options[:outputfile], 'w+').puts report.report
61
+ end
62
+
63
+ puts report.report unless options[:copypasteboard] || options[:outputfile]
@@ -0,0 +1,150 @@
1
+ require 'osx/cocoa'
2
+ require 'find'
3
+
4
+ # DsymFile - wrapper around a .dSYM bundle
5
+ #
6
+ #
7
+ class DsymFile
8
+ attr_reader :identifier, :version, :shortversionstring
9
+
10
+ # Initializes a DsymFile with a path to a dSYM Bundle
11
+ #
12
+ # Extracts CFBundleIdentifier, CFBundleVersion and CFBundleShortVersionString from the Info.plist file inside the bundle
13
+ def initialize(filename)
14
+ @info_plist = OSX::NSDictionary.dictionaryWithContentsOfFile(File.join(filename, 'Contents/Info.plist'))
15
+ return unless @info_plist
16
+ @identifier = @info_plist['CFBundleIdentifier'].to_s
17
+ @version = @info_plist['CFBundleVersion'].to_s
18
+ @shortversionstring = @info_plist['CFBundleShortVersionString'].to_s
19
+ @filename = filename
20
+ end # initialize
21
+
22
+ # Matches Report?
23
+ #
24
+ # Checks if the Bundle Identifier, Bundle Version and Bundle Short Version String of a given Crashreport matches to this dSYM Bundle
25
+ def matches_report?(report)
26
+ false
27
+ true if @identifier =~ /#{report.identifier}/ && @version == report.version && @shortversionstring == report.shortversion
28
+ end
29
+
30
+ # return the filename
31
+ def to_s
32
+ @filename
33
+ end
34
+ end # class DsymFile
35
+
36
+ # Symbolized
37
+ #
38
+ # A symbol of the Crashreport that has been desymbolized with gdb
39
+ class Symbolized
40
+ attr_reader :startaddress, :endaddress, :line, :symbol, :filename
41
+ # Initialize with an output line from gdb. This will extract the addresses, linenumber and source-file
42
+ def initialize(s)
43
+ s.gsub(/Line (\d*) of "(.*)" starts at address (0x[0-9a-f]*) <(.*)> and ends at (0x[0-9a-f]*)/).to_a
44
+ @line = $1
45
+ @filename = $2
46
+ @startaddress = $3.hex if $3
47
+ @symbol = $4
48
+ @endaddress = $5.hex if $3
49
+ end
50
+ end
51
+
52
+ # A class representing a crashreport
53
+ #
54
+ # This must be initialized with the crashreport as plain text, a path where to look for .dSYM bundlles can be given.
55
+ # The report can be de-symbolized with symbolicate!
56
+ class Crashreport
57
+
58
+ @addresses = nil
59
+ @dsymfile = nil
60
+ @isSymbolicated = false;
61
+ @cmdfilepath = nil;
62
+
63
+ attr_reader :identifier, :version, :shortversion, :report
64
+
65
+ # Extracts the address from a crashreport-line
66
+ def self.address_from_report_line(s)
67
+ a = s[/(0x[0-9a-f]+)/, 1]
68
+ return a.hex if a
69
+ nil
70
+ end
71
+
72
+ # Creates a new Crashreport object
73
+ #
74
+ # r is the crash report as string. dsymfile is a path where this object will look for a matching .dSYM bundle
75
+ def initialize(r, dsymfile=nil)
76
+ @report = r
77
+ @dsymfile = dsymfile
78
+ @identifier = @report[/Identifier: (.*)/, 1]
79
+ @shortversion = @report[/Version: (.*) \((.*)\)/, 1]
80
+ @version = @report[/Version: (.*) \((.*)\)/, 2]
81
+ findDysmFile(dsymfile)
82
+ end
83
+
84
+ # Find dSYM Bundle
85
+ #
86
+ # Look for a matching dSYM bundle. Use the current directory when nil
87
+ def findDysmFile(searchpath)
88
+ Find.find(searchpath || '.') do |f|
89
+ if f =~ /.dSYM/
90
+ dsymfile = DsymFile.new(f)
91
+ if dsymfile.matches_report? self
92
+ @dsymfile = dsymfile
93
+ return
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ # returns an array of all adresses found in the crashreport
100
+ def addresses
101
+ return @addresses if @addresses
102
+ @addresses = []
103
+ @report.lines.each do |l|
104
+ a = Crashreport.address_from_report_line(l)
105
+ @addresses << a if a
106
+ end
107
+ @addresses
108
+ end
109
+
110
+ # de-symbolizes the crashreport
111
+ #
112
+ # The get the report with .report aftwards
113
+ def symbolicate!
114
+ return if @isSymbolicated
115
+ buildgdbcommandfile
116
+ gdbout = rungdb
117
+ @symbols = []
118
+ gdbout.lines.each do |l|
119
+ @symbols << Symbolized.new(l)
120
+ end
121
+
122
+ addresses.each do |a|
123
+ @symbols.each do |s|
124
+ if s.startaddress && a >= s.startaddress && a <= s.endaddress
125
+ report.gsub!(/(0x.*#{a.to_s(16)}) (.*)/, "#{$1} #{s.symbol} (#{s.filename}:#{s.line})")
126
+ end # address matches
127
+ end # @symbols.each
128
+ end# addresses.each
129
+ @isSymbolicated = true
130
+ end # symbolicate!
131
+
132
+ private
133
+ # runs gdb with the command file created by buildgdbcommandfile
134
+ def rungdb
135
+ gdbcmd = "gdb --batch --quiet -x \"#{@cmdfilepath}\" \"#{@dsymfile}\""
136
+ gdbout = `#{gdbcmd}`
137
+ gdbout
138
+ end
139
+
140
+ # build a command-file for gdb
141
+ def buildgdbcommandfile
142
+ return if @cmdfilepath
143
+ @cmdfilepath = '/tmp/symsymcmd.txt'
144
+ cmdfile = File.new(@cmdfilepath, 'w+')
145
+ self.addresses.each do |l|
146
+ cmdfile << "info line *#{l}\n"
147
+ end
148
+ cmdfile.close
149
+ end # buildgdbcommandfile
150
+ end # class Crashreport
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: symsym
3
+ version: !ruby/object:Gem::Version
4
+ hash: 63
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
+ platform: ruby
12
+ authors:
13
+ - Ulrich Zurucker
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-09 00:00:00 +02:00
19
+ default_executable: symsym
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ type: :development
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 6
33
+ - 0
34
+ version: 1.6.0
35
+ name: jeweler
36
+ version_requirements: *id001
37
+ description: symsym can be used to symbolize crashlogs from dSYM files
38
+ email: ulizurucker@googlemail.com
39
+ executables:
40
+ - symsym
41
+ extensions: []
42
+
43
+ extra_rdoc_files:
44
+ - LICENSE.txt
45
+ - README.md
46
+ - README.rdoc
47
+ files:
48
+ - .document
49
+ - Gemfile
50
+ - Gemfile.lock
51
+ - LICENSE.txt
52
+ - README.md
53
+ - README.rdoc
54
+ - Rakefile
55
+ - VERSION
56
+ - bin/symsym
57
+ - lib/symsym.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/sononum/symsym
60
+ licenses:
61
+ - MIT
62
+ post_install_message:
63
+ rdoc_options: []
64
+
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ hash: 3
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ none: false
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ hash: 3
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ requirements: []
86
+
87
+ rubyforge_project:
88
+ rubygems_version: 1.5.2
89
+ signing_key:
90
+ specification_version: 3
91
+ summary: Crashlog symbolizer for Mac OS X
92
+ test_files: []
93
+