Class: Tracetool::Android::NativeTraceScanner

Inherits:
Object
  • Object
show all
Extended by:
NativeTraceEnhancer
Defined in:
lib/tracetool/android/native.rb

Overview

Processes native traces

Constant Summary collapse

TRACE_DELIMETER =

Initial sequence of asterisks which marks begining of trace body

'*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***'.freeze
RX_INITIAL_ASTERISKS =
/#{TRACE_DELIMETER.gsub('*', '\*')}/
RX_PC_ADDRESS =

Contains address line like

“‘ pc 00000000004321ec libfoo.so “`

/pc \d+/
RX_PACKED_FORMAT =

Format of packed trace. Consists of one or more trace blocks.

  • Each block starts with ‘<<<` and ends with `>>>`.

  • Each block contains one or more lines

  • Lines delimited with ;

  • Line consists of

** pointer address ‘/d+/` ** library (so) name `/[^ ]+/` ** symbol name `/[^ ]+/`, if present ** symbol offset `/d+/`

Last two entries can be missing.

/^(<<<(\d+ [^ ]+ ([^ ]+ \d+)?;)+>>>)+$/

Constants included from NativeTraceEnhancer

Tracetool::Android::NativeTraceEnhancer::NATIVE_DUMP_HEADER

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NativeTraceEnhancer

add_header, unpack

Constructor Details

#initialize(string) ⇒ NativeTraceScanner

Returns a new instance of NativeTraceScanner.

Parameters:

  • string (String)

    well formed native android stack trace

See Also:



91
92
93
# File 'lib/tracetool/android/native.rb', line 91

def initialize(string)
  @trace = string
end

Class Method Details

.[](string) ⇒ NativeTraceScanner

With given potential stack trace string create scanner if possible

Parameters:

  • string (String)

    trace

Returns:



144
145
146
147
148
149
150
151
152
# File 'lib/tracetool/android/native.rb', line 144

def [](string)
  if packed? string
    new(unpack(string))
  elsif with_header? string
    new(string)
  elsif without_header? string
    new(add_header(string))
  end
end

.address_lines?(lines) ⇒ Boolean

Returns:

  • (Boolean)


130
131
132
133
134
# File 'lib/tracetool/android/native.rb', line 130

def address_lines?(lines)
  lines.all? do |line|
    RX_PC_ADDRESS.match(line)
  end
end

.match(string) ⇒ Object

Tells if provided string is a ndk trace

Returns:

  • truthy or falsey value



113
114
115
116
# File 'lib/tracetool/android/native.rb', line 113

def match(string)
  return false if string.empty?
  packed?(string) || with_header?(string) || without_header?(string)
end

.packed?(string) ⇒ Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/tracetool/android/native.rb', line 118

def packed?(string)
  RX_PACKED_FORMAT.match(string)
end

.with_header?(string) ⇒ Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/tracetool/android/native.rb', line 136

def with_header?(string)
  RX_INITIAL_ASTERISKS.match(string)
end

.without_header?(string) ⇒ Boolean

Returns:

  • (Boolean)


122
123
124
125
126
127
128
# File 'lib/tracetool/android/native.rb', line 122

def without_header?(string)
  lines = string.split("\n")
  return true if address_lines?(lines)

  first, *rest = lines
  first.include?('backtrace:') && address_lines?(rest)
end

Instance Method Details

#process(ctx) ⇒ String

Returns desymbolicated stack trace.

Parameters:

  • ctx (OpenStruct)

    context object containing ‘symbols` field with path to symbols dir

Returns:

  • (String)

    desymbolicated stack trace



98
99
100
101
102
103
104
105
106
# File 'lib/tracetool/android/native.rb', line 98

def process(ctx)
  symbols = File.join(ctx.symbols, 'local')
  symbols = if ctx.arch
              File.join(symbols, ctx.arch)
            else
              Dir[File.join(symbols, '*')].first || symbols
            end
  Pipe['ndk-stack', '-sym', symbols] << @trace
end