Class: Squash::Symbolicator

Inherits:
Object
  • Object
show all
Defined in:
lib/squash/symbolicator.rb

Overview

Uses ‘dwarfdump` to generate symbolication information for a given dSYM file. Uses `POpen3` to shell out to `dwarfdump`.

Defined Under Namespace

Classes: Line, Lines, Symbol, Symbols

Instance Method Summary collapse

Constructor Details

#initialize(dsym, project_dir = nil) ⇒ Symbolicator

Creates a new symbolicator for a given dSYM file.

Parameters:

  • dsym (String)

    The path to a dSYM file (or DWARF file within).

  • project_dir (String) (defaults to: nil)

    The path to a project root that will be removed from file paths underneath that root.



30
31
32
33
# File 'lib/squash/symbolicator.rb', line 30

def initialize(dsym, project_dir=nil)
  @dsym        = dsym
  @project_dir = project_dir
end

Instance Method Details

#architecturesHash<String, String>

Returns A hash mapping architectures (such as “i386”) to the UUID for the symbolication of that architecture.

Returns:

  • (Hash<String, String>)

    A hash mapping architectures (such as “i386”) to the UUID for the symbolication of that architecture.



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/squash/symbolicator.rb', line 38

def architectures
  architectures = Hash.new

  stdin, stdout, stderr = Open3.popen3('dwarfdump', '-u', @dsym)
  stdout.each_line do |line|
    if line =~ /^UUID: ([0-9A-F\-]+) \((.+?)\) [^\s]+$/
      architectures[$2] = $1
    end
  end

  return architectures
end

#lines(arch) ⇒ Symbols

Extracts line number information from the dSYM.

Parameters:

  • arch (String)

    The architecture to extract symbols for.

Returns:

  • (Symbols)

    The line info defined in the dSYM.

See Also:



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
# File 'lib/squash/symbolicator.rb', line 107

def lines(arch)
  lines        = Lines.new
  current_line = nil

  stdin, stdout, stderr = Open3.popen3('dwarfdump', '--debug-line', "--arch=#{arch}", @dsym)
  stdout.each_line do |line|
    if current_line
      if line =~ /^include_directories\[\s+(\d+)\] = '(.+)'$/
        current_line[:include_directories][$1] = $2
      elsif line =~ /^file_names\[\s*(\d+)\]\s+(\d+)\s+0x[0-9a-f]+\s+0x[0-9a-f]+\s+(.+)$/
        current_line[:file_names][$1] = current_line[:include_directories][$2] + '/' + $3
      elsif line =~ /^            (0x[0-9a-f]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+/
        path          = current_line[:file_names][$2]
        line          = $3.to_i
        col           = $4.to_i
        start_address = $1.hex
        path.sub!(/^#{Regexp.escape @project_dir}\//, '') if @project_dir
        lines.add start_address, path, line, col
      end
    else
      if line =~ /^debug_line\[0x[0-9a-f]+\]$/
        current_line = {
            :include_directories => {},
            :file_names          => {}
        }
      end
    end
  end

  return lines
end

#symbols(arch) ⇒ Symbols

Extracts symbol information from the dSYM.

Parameters:

  • arch (String)

    The architecture to extract symbols for.

Returns:

  • (Symbols)

    The symbols defined in the dSYM.

See Also:



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
# File 'lib/squash/symbolicator.rb', line 57

def symbols(arch)
  symbolications     = Symbols.new
  current_subprogram = nil

  stdin, stdout, stderr = Open3.popen3('dwarfdump', '--debug-info', "--arch=#{arch}", @dsym)
  stdout.each_line do |line|
    if current_subprogram
      if line =~ /^\s*AT_(\w+)\(\s*(.+?)\s*\)$/
        tag   = $1
        value = $2

        case tag
          when 'name', 'decl_file' # quoted strings
            value = value[1..-2]
          when 'decl_line' # decimal integers
            value = value.to_i
          when 'prototyped', 'external' # booleans
            value = (value == '0x01')
          when 'low_pc', 'high_pc' # hex integers
            value = value.hex
        end

        current_subprogram[tag] = value
      elsif line =~ /^0x[0-9a-f]+:\s+TAG_(\w+)/
        next unless %w(low_pc high_pc decl_file decl_line name).all? { |k| current_subprogram.include? k }
        current_subprogram['decl_file'].sub!(/^#{Regexp.escape @project_dir}\//, '') if @project_dir
        symbolications.add current_subprogram['low_pc'],
                           current_subprogram['high_pc'],
                           current_subprogram['decl_file'],
                           current_subprogram['decl_line'],
                           current_subprogram['name']

        current_subprogram = ($1 == 'subprogram') ? Hash.new : nil
      end
    else
      if line =~ /^0x[0-9a-f]+:\s+TAG_subprogram\s+\[\d+\]\s+\*$/
        current_subprogram = Hash.new
      end
    end
  end

  return symbolications
end