1# Copyright 2014 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import posixpath
6
7from memory_inspector.core import symbol
8
9
10class Stacktrace(object):
11  """Models a stack-trace, which is a sequence of stack |Frame|s."""
12
13  def __init__(self):
14    self.frames = []
15
16  def Add(self, frame):
17    assert(isinstance(frame, Frame))
18    self.frames += [frame]
19
20  @property
21  def depth(self):
22    return len(self.frames)
23
24  def __getitem__(self, index):
25    return self.frames[index]
26
27  def __str__(self):
28    return ', '.join([str(x) for x in self.frames])
29
30
31class Frame(object):
32  """Models a stack frame in a |Stacktrace|. It might be symbolized or not."""
33
34  def __init__(self, address):
35    """
36    Args:
37        address: the absolute (virtual) address of the stack frame in the
38                 original process virtual address space.
39    """
40    assert(isinstance(address, (long, int)))
41    self.address = address
42    self.symbol = None
43    self.exec_file_rel_path = None
44
45    # Offset is the displacement inside the executable file, calculated as:
46    # self.address - mapping_address_of_the_so + mapping_offset_of_the_exec.
47    self.offset = None
48
49  def SetExecFileInfo(self, exec_file_rel_path, offset):
50    """Sets the base file + offset information required for symbolization.
51
52    Args:
53        exec_file_rel_path: the path of the mapped executable (binary or lib)
54            relative to the target device (e.g., /system/lib/libc.so).
55        offset: the offset in the executable.
56    """
57    assert(isinstance(offset, (long, int)))
58    self.exec_file_rel_path = exec_file_rel_path
59    self.offset = offset
60
61  def SetSymbolInfo(self, sym):
62    """Sets the symbolization information."""
63    assert(isinstance(sym, symbol.Symbol))
64    assert(not self.symbol)
65    self.symbol = sym
66
67  @property
68  def exec_file_name(self):
69    """Returns the file name (stripped of the path) of the executable."""
70    if not self.exec_file_rel_path:
71      return None
72    return posixpath.basename(self.exec_file_rel_path.replace('\\', '/'))
73
74  @property
75  def raw_address(self):
76    if self.exec_file_rel_path:
77      return '%s +0x%x' % (self.exec_file_name, self.offset)
78    else:
79      return '0x%x' % self.address
80
81  def __str__(self):
82    if self.symbol:
83      return str(self.symbol)
84    elif self.exec_file_rel_path:
85      return self.raw_address