Пример #1
0
 def testSymbols(self):
   archive = self._storage.OpenArchive('symbols', create=True)
   symbols = symbol.Symbols()
   # Symbol db is global per archive, no need to StartNewSnapshot.
   symbols.Add('foo.so', 1, symbol.Symbol('sym1', 'file1.c', 11))
   symbols.Add('bar.so', 2, symbol.Symbol('sym2', 'file2.c', 12))
   sym3 = symbol.Symbol('sym3', 'file2.c', 13)
   sym3.AddSourceLineInfo('outer_file.c', 23)
   symbols.Add('baz.so', 3, sym3)
   archive.StoreSymbols(symbols)
   symbols_deser = archive.LoadSymbols()
   self._DeepCompare(symbols, symbols_deser)
   self._storage.DeleteArchive('symbols')
Пример #2
0
    def runTest(self):
        rule_tree = native_heap_classifier.LoadRules(_TEST_RULES)
        nheap = native_heap.NativeHeap()
        mock_addr = 0
        for test_entry in _TEST_STACK_TRACES:
            mock_strace = stacktrace.Stacktrace()
            for mock_btstr in test_entry[1]:
                mock_addr += 4  # Addr is irrelevant, just keep it distinct.
                mock_frame = stacktrace.Frame(mock_addr)
                mock_frame.SetSymbolInfo(symbol.Symbol(mock_btstr))
                mock_strace.Add(mock_frame)
            nheap.Add(
                native_heap.Allocation(size=test_entry[0],
                                       count=1,
                                       stack_trace=mock_strace))

        res = native_heap_classifier.Classify(nheap, rule_tree)

        def CheckResult(node, prefix):
            node_name = prefix + node.name
            self.assertIn(node_name, _EXPECTED_RESULTS)
            self.assertEqual(node.values, _EXPECTED_RESULTS[node_name])
            for child in node.children:
                CheckResult(child, node_name + '::')

        CheckResult(res.total, '')
Пример #3
0
 def SymbolizeAsyncCallback(sym_info, stack_frame):
   if not sym_info.name:
     return
   sym = symbol.Symbol(name=sym_info.name,
                       source_file_path=sym_info.source_path,
                       line_number=sym_info.source_line)
   symbols.Add(stack_frame.exec_file_rel_path, stack_frame.offset, sym)
Пример #4
0
 def decode(self, json_str):  # pylint: disable=W0221
     d = super(SymbolsDecoder, self).decode(json_str)
     symbols = symbol.Symbols()
     for sym_key, sym_dict in d.iteritems():
         sym = symbol.Symbol(sym_dict['name'])
         for source_info in sym_dict['source_info']:
             sym.AddSourceLineInfo(**source_info)
         symbols.symbols[sym_key] = sym
     return symbols
Пример #5
0
  def testStandardRuleParsingAndProcessing(self):
    rule_tree = native_heap_classifier.LoadRules(_TEST_RULES)
    nheap = native_heap.NativeHeap()
    mock_addr = 0
    for test_entry in _TEST_STACK_TRACES:
      mock_strace = stacktrace.Stacktrace()
      for (mock_btstr, mock_source_path) in test_entry[1]:
        mock_addr += 4  # Addr is irrelevant, just keep it distinct.
        mock_frame = stacktrace.Frame(mock_addr)
        mock_frame.SetSymbolInfo(symbol.Symbol(mock_btstr, mock_source_path))
        mock_strace.Add(mock_frame)
      nheap.Add(native_heap.Allocation(
          size=test_entry[0], count=1, stack_trace=mock_strace))

    res = native_heap_classifier.Classify(nheap, rule_tree)
    self._CheckResult(res.total, '', _EXPECTED_RESULTS)
Пример #6
0
  def testInferHeuristicRules(self):
    nheap = native_heap.NativeHeap()
    mock_addr = 0
    for (mock_alloc_size, mock_source_path) in _HEURISTIC_TEST_STACK_TRACES:
      mock_strace = stacktrace.Stacktrace()
      mock_addr += 4  # Addr is irrelevant, just keep it distinct.
      mock_frame = stacktrace.Frame(mock_addr)
      mock_frame.SetSymbolInfo(symbol.Symbol(str(mock_addr), mock_source_path))
      for _ in xrange(10):  # Just repeat the same stack frame 10 times
        mock_strace.Add(mock_frame)
      nheap.Add(native_heap.Allocation(
          size=mock_alloc_size, count=1, stack_trace=mock_strace))

    rule_tree = native_heap_classifier.InferHeuristicRulesFromHeap(
        nheap, threshold=0.05)
    res = native_heap_classifier.Classify(nheap, rule_tree)
    self._CheckResult(res.total, '', _HEURISTIC_EXPECTED_RESULTS)
Пример #7
0
    def runTest(self):
        nheap = native_heap.NativeHeap()

        EXE_1_MM_BASE = 64 * PAGE_SIZE
        EXE_2_MM_BASE = 65 * PAGE_SIZE
        EXE_2_FILE_OFF = 8192
        st1 = stacktrace.Stacktrace()
        st1.Add(nheap.GetStackFrame(EXE_1_MM_BASE))
        st1.Add(nheap.GetStackFrame(EXE_1_MM_BASE + 4))

        st2 = stacktrace.Stacktrace()
        st2.Add(nheap.GetStackFrame(EXE_1_MM_BASE))
        st2.Add(nheap.GetStackFrame(EXE_2_MM_BASE + 4))
        st2.Add(nheap.GetStackFrame(EXE_2_MM_BASE + PAGE_SIZE + 4))

        # Check that GetStackFrames keeps one unique object instance per address.
        # This is to guarantee that the symbolization logic (SymbolizeUsingSymbolDB)
        # can cheaply iterate on distinct stack frames rather than re-processing
        # every stack frame for each allocation (and save memory as well).
        self.assertIs(st1[0], st2[0])
        self.assertIsNot(st1[0], st1[1])
        self.assertIsNot(st2[0], st2[1])

        alloc1 = native_heap.Allocation(start=4, size=4, stack_trace=st1)
        alloc2 = native_heap.Allocation(start=4090, size=8, stack_trace=st1)
        alloc3 = native_heap.Allocation(start=8190,
                                        size=10000,
                                        stack_trace=st2)
        nheap.Add(alloc1)
        nheap.Add(alloc2)
        nheap.Add(alloc3)

        self.assertEqual(len(nheap.allocations), 3)
        self.assertIn(alloc1, nheap.allocations)
        self.assertIn(alloc2, nheap.allocations)
        self.assertIn(alloc3, nheap.allocations)

        ############################################################################
        # Test the relativization (absolute address -> mmap + offset) logic.
        ############################################################################
        mmap = memory_map
        mmap = memory_map.Map()
        mmap.Add(
            memory_map.MapEntry(EXE_1_MM_BASE, EXE_1_MM_BASE + PAGE_SIZE - 1,
                                'rw--', '/d/exe1', 0))
        mmap.Add(
            memory_map.MapEntry(EXE_2_MM_BASE, EXE_2_MM_BASE + PAGE_SIZE - 1,
                                'rw--', 'exe2', EXE_2_FILE_OFF))
        # Entry for EXE_3 is deliberately missing to check the fallback behavior.

        nheap.RelativizeStackFrames(mmap)

        self.assertEqual(st1[0].exec_file_rel_path, '/d/exe1')
        self.assertEqual(st1[0].exec_file_name, 'exe1')
        self.assertEqual(st1[0].offset, 0)

        self.assertEqual(st1[1].exec_file_rel_path, '/d/exe1')
        self.assertEqual(st1[1].exec_file_name, 'exe1')
        self.assertEqual(st1[1].offset, 4)

        self.assertEqual(st2[0].exec_file_rel_path, '/d/exe1')
        self.assertEqual(st2[0].exec_file_name, 'exe1')
        self.assertEqual(st2[0].offset, 0)

        self.assertEqual(st2[1].exec_file_rel_path, 'exe2')
        self.assertEqual(st2[1].exec_file_name, 'exe2')
        self.assertEqual(st2[1].offset, 4 + EXE_2_FILE_OFF)

        self.assertIsNone(st2[2].exec_file_rel_path)
        self.assertIsNone(st2[2].exec_file_name)
        self.assertIsNone(st2[2].offset)

        ############################################################################
        # Test the symbolization logic.
        ############################################################################
        syms = symbol.Symbols()
        syms.Add('/d/exe1', 0, symbol.Symbol('sym1', 'src1.c', 1))  # st1[0]
        syms.Add('exe2', 4 + EXE_2_FILE_OFF, symbol.Symbol('sym3'))  # st2[1]

        nheap.SymbolizeUsingSymbolDB(syms)
        self.assertEqual(st1[0].symbol.name, 'sym1')
        self.assertEqual(st1[0].symbol.source_info[0].source_file_path,
                         'src1.c')
        self.assertEqual(st1[0].symbol.source_info[0].line_number, 1)

        # st1[1] should have no symbol info, because we didn't provide any above.
        self.assertIsNone(st1[1].symbol)

        # st2[0] and st1[0] were the same Frame. Expect identical symbols instances.
        self.assertIs(st2[0].symbol, st1[0].symbol)

        # st2[1] should have a symbols name, but no source line info.
        self.assertEqual(st2[1].symbol.name, 'sym3')
        self.assertEqual(len(st2[1].symbol.source_info), 0)

        # st2[2] should have no sym because we didn't even provide a mmap for exe3.
        self.assertIsNone(st2[2].symbol)

        ############################################################################
        # Test the resident size calculation logic (intersects mmaps and allocs).
        ############################################################################
        mmap.Add(
            memory_map.MapEntry(0, 8191, 'rw--', '', 0, resident_pages=[1]))
        mmap.Add(
            memory_map.MapEntry(8192, 12287, 'rw--', '', 0,
                                resident_pages=[1]))
        # [12k, 16k] is deliberately missing to check the fallback behavior.
        mmap.Add(
            memory_map.MapEntry(16384,
                                20479,
                                'rw--',
                                '',
                                0,
                                resident_pages=[1]))
        nheap.CalculateResidentSize(mmap)

        # alloc1 [4, 8] is fully resident because it lays in the first resident 4k.
        self.assertEqual(alloc1.resident_size, 4)

        # alloc2 [4090, 4098] should have only 6 resident bytes ([4090,4096]), but
        # not the last two, which lay on the second page which is noijt resident.
        self.assertEqual(alloc2.resident_size, 6)

        # alloc3 [8190, 18190] is split as follows (* = resident):
        #  [8190, 8192]: these 2 bytes are NOT resident, they lay in the 2nd page.
        # *[8192, 12288]: the 3rd page is resident and is fully covered by alloc3.
        #  [12288, 16384]: the 4th page is fully covered as well, but not resident.
        # *[16384, 18190]: the 5th page is partially covered and resident.
        self.assertEqual(alloc3.resident_size,
                         (12288 - 8192) + (18190 - 16384))