1f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch#!/usr/bin/env python 2f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# 33ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch# Copyright 2012 the V8 project authors. All rights reserved. 4f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# Redistribution and use in source and binary forms, with or without 5f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# modification, are permitted provided that the following conditions are 6f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# met: 7f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# 8f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# * Redistributions of source code must retain the above copyright 9f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# notice, this list of conditions and the following disclaimer. 10f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# * Redistributions in binary form must reproduce the above 11f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# copyright notice, this list of conditions and the following 12f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# disclaimer in the documentation and/or other materials provided 13f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# with the distribution. 14f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# * Neither the name of Google Inc. nor the names of its 15f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# contributors may be used to endorse or promote products derived 16f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# from this software without specific prior written permission. 17f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# 18f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 30f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport bisect 31f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport collections 32f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport ctypes 33e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochimport disasm 34f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport mmap 35f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport optparse 36f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport os 37f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport re 38f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport subprocess 39f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport sys 40f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochimport time 41f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 42f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 43f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochUSAGE="""usage: %prog [OPTION]... 44f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 45f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochAnalyses V8 and perf logs to produce profiles. 46f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 47f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPerf logs can be collected using a command like: 48f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch $ perf record -R -e cycles -c 10000 -f -i ./shell bench.js --ll-prof 49f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # -R: collect all data 50f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # -e cycles: use cpu-cycles event (run "perf list" for details) 51f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # -c 10000: write a sample after each 10000 events 52f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # -f: force output file overwrite 53f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # -i: limit profiling to our process and the kernel 54f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # --ll-prof shell flag enables the right V8 logs 55f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochThis will produce a binary trace file (perf.data) that %prog can analyse. 56f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 57f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochExamples: 58f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Print flat profile with annotated disassembly for the 10 top 59f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # symbols. Use default log names and include the snapshot log. 60f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch $ %prog --snapshot --disasm-top=10 61f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 62f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Print flat profile with annotated disassembly for all used symbols. 63f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Use default log names and include kernel symbols into analysis. 64f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch $ %prog --disasm-all --kernel 65f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 66f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Print flat profile. Use custom log names. 67f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch $ %prog --log=foo.log --snapshot-log=snap-foo.log --trace=foo.data --snapshot 68f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch""" 69f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 70f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 71f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# Must match kGcFakeMmap. 72f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochV8_GC_FAKE_MMAP = "/tmp/__v8_gc__" 73f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 74f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochJS_ORIGIN = "js" 75f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochJS_SNAPSHOT_ORIGIN = "js-snapshot" 76f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 77e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochOBJDUMP_BIN = disasm.OBJDUMP_BIN 78f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 79f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 80f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass Code(object): 81f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch """Code object.""" 82f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 83f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch _id = 0 84f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 85f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self, name, start_address, end_address, origin, origin_offset): 86f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.id = Code._id 87f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch Code._id += 1 88f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.name = name 89f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.other_names = None 90f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.start_address = start_address 91f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.end_address = end_address 92f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.origin = origin 93f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.origin_offset = origin_offset 94f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.self_ticks = 0 95f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.self_ticks_map = None 96f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.callee_ticks = None 97f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 98f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def AddName(self, name): 99f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert self.name != name 100f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.other_names is None: 101f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.other_names = [name] 102f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return 103f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not name in self.other_names: 104f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.other_names.append(name) 105f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 106f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def FullName(self): 107f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.other_names is None: 108f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return self.name 109f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.other_names.sort() 110f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return "%s (aka %s)" % (self.name, ", ".join(self.other_names)) 111f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 112f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def IsUsed(self): 113f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return self.self_ticks > 0 or self.callee_ticks is not None 114f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 115f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Tick(self, pc): 116f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.self_ticks += 1 117f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.self_ticks_map is None: 118f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.self_ticks_map = collections.defaultdict(lambda: 0) 119f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch offset = pc - self.start_address 120f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.self_ticks_map[offset] += 1 121f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 122f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def CalleeTick(self, callee): 123f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.callee_ticks is None: 124f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.callee_ticks = collections.defaultdict(lambda: 0) 125f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.callee_ticks[callee] += 1 126f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def PrintAnnotated(self, arch, options): 128f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.self_ticks_map is None: 129f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks_map = [] 130f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 131f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks_map = self.self_ticks_map.items() 132f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Convert the ticks map to offsets and counts arrays so that later 133f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # we can do binary search in the offsets array. 134f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks_map.sort(key=lambda t: t[0]) 135f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks_offsets = [t[0] for t in ticks_map] 136f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks_counts = [t[1] for t in ticks_map] 137f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Get a list of disassembled lines and their addresses. 138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lines = self._GetDisasmLines(arch, options) 139f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if len(lines) == 0: 140f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return 141f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Print annotated lines. 142f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch address = lines[0][0] 143f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch total_count = 0 144f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for i in xrange(len(lines)): 145f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch start_offset = lines[i][0] - address 146f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if i == len(lines) - 1: 147f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch end_offset = self.end_address - self.start_address 148f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 149f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch end_offset = lines[i + 1][0] - address 150f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Ticks (reported pc values) are not always precise, i.e. not 151f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # necessarily point at instruction starts. So we have to search 152f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # for ticks that touch the current instruction line. 153f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch j = bisect.bisect_left(ticks_offsets, end_offset) 154f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch count = 0 155f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for offset, cnt in reversed(zip(ticks_offsets[:j], ticks_counts[:j])): 156f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if offset < start_offset: 157f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch break 158f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch count += cnt 159f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch total_count += count 160f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch count = 100.0 * count / self.self_ticks 161f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if count >= 0.01: 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch print "%15.2f %x: %s" % (count, lines[i][0], lines[i][1]) 163f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch print "%s %x: %s" % (" " * 15, lines[i][0], lines[i][1]) 165f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print 166f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert total_count == self.self_ticks, \ 167f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Lost ticks (%d != %d) in %s" % (total_count, self.self_ticks, self) 168f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 169f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __str__(self): 170f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return "%s [0x%x, 0x%x) size: %d origin: %s" % ( 171f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.name, 172f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.start_address, 173f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.end_address, 174f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.end_address - self.start_address, 175f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.origin) 176f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def _GetDisasmLines(self, arch, options): 178f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.origin == JS_ORIGIN or self.origin == JS_SNAPSHOT_ORIGIN: 179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch inplace = False 180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch filename = options.log + ".ll" 181f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch inplace = True 183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch filename = self.origin 184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return disasm.GetDisasmLines(filename, 185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch self.origin_offset, 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch self.end_address - self.start_address, 187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch arch, 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch inplace) 189f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 190f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 191f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass CodePage(object): 192f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch """Group of adjacent code objects.""" 193f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 194f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch SHIFT = 12 # 4K pages 195f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch SIZE = (1 << SHIFT) 196f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch MASK = ~(SIZE - 1) 197f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 198f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch @staticmethod 199f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def PageAddress(address): 200f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return address & CodePage.MASK 201f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 202f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch @staticmethod 203f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def PageId(address): 204f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return address >> CodePage.SHIFT 205f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 206f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch @staticmethod 207f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def PageAddressFromId(id): 208f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return id << CodePage.SHIFT 209f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 210f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self, address): 211f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.address = address 212f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_objects = [] 213f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 214f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Add(self, code): 215f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_objects.append(code) 216f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 217f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Remove(self, code): 218f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_objects.remove(code) 219f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 220f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Find(self, pc): 221f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code_objects = self.code_objects 222f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for i, code in enumerate(code_objects): 223f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code.start_address <= pc < code.end_address: 224f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code_objects[0], code_objects[i] = code, code_objects[0] 225f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return code 226f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return None 227f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 228f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __iter__(self): 229f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return self.code_objects.__iter__() 230f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 231f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 232f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass CodeMap(object): 233f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch """Code object map.""" 234f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 235f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self): 236f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.pages = {} 237f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.min_address = 1 << 64 238f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.max_address = -1 239f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 240f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Add(self, code, max_pages=-1): 241f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page_id = CodePage.PageId(code.start_address) 242f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch limit_id = CodePage.PageId(code.end_address + CodePage.SIZE - 1) 243f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch pages = 0 244f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch while page_id < limit_id: 245f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if max_pages >= 0 and pages > max_pages: 246f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print >>sys.stderr, \ 247f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Warning: page limit (%d) reached for %s [%s]" % ( 248f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch max_pages, code.name, code.origin) 249f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch break 250f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if page_id in self.pages: 251f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page = self.pages[page_id] 252f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 253f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page = CodePage(CodePage.PageAddressFromId(page_id)) 254f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.pages[page_id] = page 255f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page.Add(code) 256f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page_id += 1 257f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch pages += 1 258f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.min_address = min(self.min_address, code.start_address) 259f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.max_address = max(self.max_address, code.end_address) 260f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 261f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Remove(self, code): 262f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page_id = CodePage.PageId(code.start_address) 263f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch limit_id = CodePage.PageId(code.end_address + CodePage.SIZE - 1) 264f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch removed = False 265f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch while page_id < limit_id: 266f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if page_id not in self.pages: 267f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page_id += 1 268f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 269f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page = self.pages[page_id] 270f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page.Remove(code) 271f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch removed = True 272f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page_id += 1 273f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return removed 274f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 275f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def AllCode(self): 276f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for page in self.pages.itervalues(): 277f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for code in page: 278f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if CodePage.PageAddress(code.start_address) == page.address: 279f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch yield code 280f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 281f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def UsedCode(self): 282f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for code in self.AllCode(): 283f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code.IsUsed(): 284f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch yield code 285f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 286f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Print(self): 287f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for code in self.AllCode(): 288f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print code 289f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 290f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Find(self, pc): 291f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if pc < self.min_address or pc >= self.max_address: 292f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return None 293f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch page_id = CodePage.PageId(pc) 294f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if page_id not in self.pages: 295f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return None 296f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return self.pages[page_id].Find(pc) 297f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 298f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 299f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass CodeInfo(object): 300f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch """Generic info about generated code objects.""" 301f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 302f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self, arch, header_size): 303f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.arch = arch 304f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.header_size = header_size 305f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 306f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass SnapshotLogReader(object): 308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch """V8 snapshot log reader.""" 309f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _SNAPSHOT_CODE_NAME_RE = re.compile( 311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch r"snapshot-code-name,(\d+),\"(.*)\"") 312f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def __init__(self, log_name): 314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_name = log_name 315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def ReadNameMap(self): 317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch log = open(self.log_name, "r") 318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch try: 319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch snapshot_pos_to_name = {} 320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for line in log: 321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch match = SnapshotLogReader._SNAPSHOT_CODE_NAME_RE.match(line) 322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if match: 323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pos = int(match.group(1)) 324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name = match.group(2) 325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch snapshot_pos_to_name[pos] = name 326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch finally: 327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch log.close() 328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return snapshot_pos_to_name 329f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 330f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass LogReader(object): 332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch """V8 low-level (binary) log reader.""" 333f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _ARCH_TO_POINTER_TYPE_MAP = { 335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "ia32": ctypes.c_uint32, 336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "arm": ctypes.c_uint32, 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "mips": ctypes.c_uint32, 338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "x64": ctypes.c_uint64 339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 340f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _CODE_CREATE_TAG = "C" 342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _CODE_MOVE_TAG = "M" 343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _CODE_DELETE_TAG = "D" 344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _SNAPSHOT_POSITION_TAG = "P" 345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _CODE_MOVING_GC_TAG = "G" 346f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def __init__(self, log_name, code_map, snapshot_pos_to_name): 348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_file = open(log_name, "r") 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log = mmap.mmap(self.log_file.fileno(), 0, mmap.MAP_PRIVATE) 350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos = 0 351f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_map = code_map 352f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.snapshot_pos_to_name = snapshot_pos_to_name 353f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.address_to_snapshot_name = {} 354f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.arch = self.log[:self.log.find("\0")] 356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += len(self.arch) + 1 357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch assert self.arch in LogReader._ARCH_TO_POINTER_TYPE_MAP, \ 358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "Unsupported architecture %s" % self.arch 359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch pointer_type = LogReader._ARCH_TO_POINTER_TYPE_MAP[self.arch] 360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.code_create_struct = LogReader._DefineStruct([ 362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("name_size", ctypes.c_int32), 363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("code_address", pointer_type), 364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("code_size", ctypes.c_int32)]) 365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.code_move_struct = LogReader._DefineStruct([ 367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("from_address", pointer_type), 368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("to_address", pointer_type)]) 369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.code_delete_struct = LogReader._DefineStruct([ 371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("address", pointer_type)]) 372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.snapshot_position_struct = LogReader._DefineStruct([ 374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("address", pointer_type), 375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ("position", ctypes.c_int32)]) 376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 377257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def ReadUpToGC(self): 378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch while self.log_pos < self.log.size(): 379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch tag = self.log[self.log_pos] 380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += 1 381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if tag == LogReader._CODE_MOVING_GC_TAG: 383f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.address_to_snapshot_name.clear() 384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return 385f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if tag == LogReader._CODE_CREATE_TAG: 387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch event = self.code_create_struct.from_buffer(self.log, self.log_pos) 388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += ctypes.sizeof(event) 389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch start_address = event.code_address 390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch end_address = start_address + event.code_size 391f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if start_address in self.address_to_snapshot_name: 392f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch name = self.address_to_snapshot_name[start_address] 393f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch origin = JS_SNAPSHOT_ORIGIN 394f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name = self.log[self.log_pos:self.log_pos + event.name_size] 396f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch origin = JS_ORIGIN 397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += event.name_size 398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch origin_offset = self.log_pos 399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += event.code_size 400f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = Code(name, start_address, end_address, origin, origin_offset) 401f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch conficting_code = self.code_map.Find(start_address) 402f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if conficting_code: 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if not (conficting_code.start_address == code.start_address and 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch conficting_code.end_address == code.end_address): 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch self.code_map.Remove(conficting_code) 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch else: 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LogReader._HandleCodeConflict(conficting_code, code) 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch # TODO(vitalyr): this warning is too noisy because of our 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch # attempts to reconstruct code log from the snapshot. 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch # print >>sys.stderr, \ 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch # "Warning: Skipping duplicate code log entry %s" % code 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch continue 413f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_map.Add(code) 414f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 415f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if tag == LogReader._CODE_MOVE_TAG: 417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch event = self.code_move_struct.from_buffer(self.log, self.log_pos) 418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += ctypes.sizeof(event) 419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch old_start_address = event.from_address 420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch new_start_address = event.to_address 421f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if old_start_address == new_start_address: 422f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Skip useless code move entries. 423f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 424f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = self.code_map.Find(old_start_address) 425f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not code: 426f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print >>sys.stderr, "Warning: Not found %x" % old_start_address 427f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 428f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert code.start_address == old_start_address, \ 429f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Inexact move address %x for %s" % (old_start_address, code) 430f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_map.Remove(code) 431f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch size = code.end_address - code.start_address 432f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code.start_address = new_start_address 433f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code.end_address = new_start_address + size 434f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_map.Add(code) 435f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 436f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if tag == LogReader._CODE_DELETE_TAG: 438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch event = self.code_delete_struct.from_buffer(self.log, self.log_pos) 439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += ctypes.sizeof(event) 440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch old_start_address = event.address 441f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = self.code_map.Find(old_start_address) 442f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not code: 443f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print >>sys.stderr, "Warning: Not found %x" % old_start_address 444f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 445f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert code.start_address == old_start_address, \ 446f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Inexact delete address %x for %s" % (old_start_address, code) 447f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.code_map.Remove(code) 448f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 449f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if tag == LogReader._SNAPSHOT_POSITION_TAG: 451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch event = self.snapshot_position_struct.from_buffer(self.log, 452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos) 453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_pos += ctypes.sizeof(event) 454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch start_address = event.address 455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch snapshot_pos = event.position 456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if snapshot_pos in self.snapshot_pos_to_name: 457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.address_to_snapshot_name[start_address] = \ 458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.snapshot_pos_to_name[snapshot_pos] 459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch continue 460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch assert False, "Unknown tag %s" % tag 462f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 463f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Dispose(self): 464f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.log.close() 465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch self.log_file.close() 466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch @staticmethod 468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch def _DefineStruct(fields): 469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch class Struct(ctypes.Structure): 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch _fields_ = fields 471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Struct 472f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 473f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch @staticmethod 474f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def _HandleCodeConflict(old_code, new_code): 475f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert (old_code.start_address == new_code.start_address and 476f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch old_code.end_address == new_code.end_address), \ 477f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Conficting code log entries %s and %s" % (old_code, new_code) 478f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if old_code.name == new_code.name: 479f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return 480f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Code object may be shared by a few functions. Collect the full 481f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # set of names. 482f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch old_code.AddName(new_code.name) 483f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 484f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 485f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass Descriptor(object): 486f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch """Descriptor of a structure in the binary trace log.""" 487f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 488f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch CTYPE_MAP = { 489f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "u16": ctypes.c_uint16, 490f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "u32": ctypes.c_uint32, 491f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "u64": ctypes.c_uint64 492f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch } 493f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 494f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self, fields): 495f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch class TraceItem(ctypes.Structure): 496f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch _fields_ = Descriptor.CtypesFields(fields) 497f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 498f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __str__(self): 499f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return ", ".join("%s: %s" % (field, self.__getattribute__(field)) 500f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for field, _ in TraceItem._fields_) 501f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 502f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.ctype = TraceItem 503f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 504f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Read(self, trace, offset): 505f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return self.ctype.from_buffer(trace, offset) 506f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 507f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch @staticmethod 508f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def CtypesFields(fields): 509f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return [(field, Descriptor.CTYPE_MAP[format]) for (field, format) in fields] 510f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 511f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 512f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# Please see http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=tree;f=tools/perf 513f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# for the gory details. 514f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 515f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 516f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochTRACE_HEADER_DESC = Descriptor([ 517f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("magic", "u64"), 518f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("size", "u64"), 519f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("attr_size", "u64"), 520f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("attrs_offset", "u64"), 521f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("attrs_size", "u64"), 522f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("data_offset", "u64"), 523f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("data_size", "u64"), 524f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("event_types_offset", "u64"), 525f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("event_types_size", "u64") 526f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch]) 527f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 528f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 529f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_EVENT_ATTR_DESC = Descriptor([ 530f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("type", "u32"), 531f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("size", "u32"), 532f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("config", "u64"), 533f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("sample_period_or_freq", "u64"), 534f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("sample_type", "u64"), 535f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("read_format", "u64"), 536f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("flags", "u64"), 537f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("wakeup_events_or_watermark", "u32"), 538f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("bt_type", "u32"), 539f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("bp_addr", "u64"), 540f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("bp_len", "u64"), 541f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch]) 542f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 543f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 544f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_EVENT_HEADER_DESC = Descriptor([ 545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("type", "u32"), 546f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("misc", "u16"), 547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("size", "u16") 548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch]) 549f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_MMAP_EVENT_BODY_DESC = Descriptor([ 552f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("pid", "u32"), 553f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("tid", "u32"), 554f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("addr", "u64"), 555f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("len", "u64"), 556f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("pgoff", "u64") 557f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch]) 558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 559f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 560f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# perf_event_attr.sample_type bits control the set of 561f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch# perf_sample_event fields. 562f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_IP = 1 << 0 563f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_TID = 1 << 1 564f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_TIME = 1 << 2 565f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_ADDR = 1 << 3 566f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_READ = 1 << 4 567f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_CALLCHAIN = 1 << 5 568f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_ID = 1 << 6 569f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_CPU = 1 << 7 570f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_PERIOD = 1 << 8 571f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_STREAM_ID = 1 << 9 572f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_RAW = 1 << 10 573f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 574f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 575f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_EVENT_BODY_FIELDS = [ 576f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("ip", "u64", PERF_SAMPLE_IP), 577f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("pid", "u32", PERF_SAMPLE_TID), 578f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("tid", "u32", PERF_SAMPLE_TID), 579f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("time", "u64", PERF_SAMPLE_TIME), 580f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("addr", "u64", PERF_SAMPLE_ADDR), 581f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("id", "u64", PERF_SAMPLE_ID), 582f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("stream_id", "u64", PERF_SAMPLE_STREAM_ID), 583f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("cpu", "u32", PERF_SAMPLE_CPU), 584f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("res", "u32", PERF_SAMPLE_CPU), 585f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("period", "u64", PERF_SAMPLE_PERIOD), 586f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Don't want to handle read format that comes after the period and 587f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # before the callchain and has variable size. 588f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ("nr", "u64", PERF_SAMPLE_CALLCHAIN) 589f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Raw data follows the callchain and is ignored. 590f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch] 591f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 592f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 593f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_SAMPLE_EVENT_IP_FORMAT = "u64" 594f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 595f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 596f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_RECORD_MMAP = 1 597f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_RECORD_SAMPLE = 9 598f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 599f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 600f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass TraceReader(object): 601f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch """Perf (linux-2.6/tools/perf) trace file reader.""" 602f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 603f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch _TRACE_HEADER_MAGIC = 4993446653023372624 604f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 605f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self, trace_name): 606f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.trace_file = open(trace_name, "r") 607f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.trace = mmap.mmap(self.trace_file.fileno(), 0, mmap.MAP_PRIVATE) 608f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.trace_header = TRACE_HEADER_DESC.Read(self.trace, 0) 609f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.trace_header.magic != TraceReader._TRACE_HEADER_MAGIC: 610f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print >>sys.stderr, "Warning: unsupported trace header magic" 611f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.offset = self.trace_header.data_offset 612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.limit = self.trace_header.data_offset + self.trace_header.data_size 613f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert self.limit <= self.trace.size(), \ 614f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Trace data limit exceeds trace file size" 615f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.header_size = ctypes.sizeof(PERF_EVENT_HEADER_DESC.ctype) 616f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert self.trace_header.attrs_size != 0, \ 617f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "No perf event attributes found in the trace" 618f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch perf_event_attr = PERF_EVENT_ATTR_DESC.Read(self.trace, 619f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.trace_header.attrs_offset) 620f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.sample_event_body_desc = self._SampleEventBodyDesc( 621f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch perf_event_attr.sample_type) 622f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.callchain_supported = \ 623f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch (perf_event_attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 624f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.callchain_supported: 625f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.ip_struct = Descriptor.CTYPE_MAP[PERF_SAMPLE_EVENT_IP_FORMAT] 626f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.ip_size = ctypes.sizeof(self.ip_struct) 627f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 628f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def ReadEventHeader(self): 629f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if self.offset >= self.limit: 630f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return None, 0 631f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch offset = self.offset 632f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch header = PERF_EVENT_HEADER_DESC.Read(self.trace, self.offset) 633f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.offset += header.size 634f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return header, offset 635f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 636f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def ReadMmap(self, header, offset): 637f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_info = PERF_MMAP_EVENT_BODY_DESC.Read(self.trace, 638f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch offset + self.header_size) 6393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch # Read null-terminated filename. 640f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch filename = self.trace[offset + self.header_size + ctypes.sizeof(mmap_info): 6413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch offset + header.size] 6423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch mmap_info.filename = filename[:filename.find(chr(0))] 643f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return mmap_info 644f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 645f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def ReadSample(self, header, offset): 646f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch sample = self.sample_event_body_desc.Read(self.trace, 647f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch offset + self.header_size) 648f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not self.callchain_supported: 649f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return sample 650f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch sample.ips = [] 651f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch offset += self.header_size + ctypes.sizeof(sample) 652f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for _ in xrange(sample.nr): 653f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch sample.ips.append( 654f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.ip_struct.from_buffer(self.trace, offset).value) 655f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch offset += self.ip_size 656f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return sample 657f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 658f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Dispose(self): 659f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.trace.close() 660f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.trace_file.close() 661f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 662f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def _SampleEventBodyDesc(self, sample_type): 663f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert (sample_type & PERF_SAMPLE_READ) == 0, \ 664f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "Can't hande read format in samples" 665f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch fields = [(field, format) 666f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for (field, format, bit) in PERF_SAMPLE_EVENT_BODY_FIELDS 667f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if (bit & sample_type) != 0] 668f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return Descriptor(fields) 669f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 670f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 671f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochOBJDUMP_SECTION_HEADER_RE = re.compile( 672f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch r"^\s*\d+\s(\.\S+)\s+[a-f0-9]") 673f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochOBJDUMP_SYMBOL_LINE_RE = re.compile( 674f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch r"^([a-f0-9]+)\s(.{7})\s(\S+)\s+([a-f0-9]+)\s+(?:\.hidden\s+)?(.*)$") 675f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochOBJDUMP_DYNAMIC_SYMBOLS_START_RE = re.compile( 6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r"^DYNAMIC SYMBOL TABLE") 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochOBJDUMP_SKIP_RE = re.compile( 6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r"^.*ld\.so\.cache$") 679f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochKERNEL_ALLSYMS_FILE = "/proc/kallsyms" 680f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochPERF_KERNEL_ALLSYMS_RE = re.compile( 681f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch r".*kallsyms.*") 682f87a203d89e1bbb6708282e0b64dbd13d59b723dBen MurdochKERNEL_ALLSYMS_LINE_RE = re.compile( 683f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch r"^([a-f0-9]+)\s(?:t|T)\s(\S+)$") 684f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 685f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 686f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochclass LibraryRepo(object): 687f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def __init__(self): 688f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.infos = [] 689f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.names = set() 690f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.ticks = {} 691f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 692f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Load(self, mmap_info, code_map, options): 693f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Skip kernel mmaps when requested using the fact that their tid 694f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # is 0. 695f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if mmap_info.tid == 0 and not options.kernel: 696f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return True 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if OBJDUMP_SKIP_RE.match(mmap_info.filename): 6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return True 699f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if PERF_KERNEL_ALLSYMS_RE.match(mmap_info.filename): 700f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return self._LoadKernelSymbols(code_map) 701f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.infos.append(mmap_info) 702f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_info.ticks = 0 703f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_info.unique_name = self._UniqueMmapName(mmap_info) 704f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not os.path.exists(mmap_info.filename): 705f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return True 706f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Request section headers (-h), symbols (-t), and dynamic symbols 707f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # (-T) from objdump. 708f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Unfortunately, section headers span two lines, so we have to 709f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # keep the just seen section name (from the first line in each 710f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # section header) in the after_section variable. 711f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch process = subprocess.Popen( 712f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "%s -h -t -T -C %s" % (OBJDUMP_BIN, mmap_info.filename), 713f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 714f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch pipe = process.stdout 715f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch after_section = None 716f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code_sections = set() 717f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch reloc_sections = set() 718f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch dynamic = False 719f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch try: 720f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for line in pipe: 721f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if after_section: 722f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if line.find("CODE") != -1: 723f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code_sections.add(after_section) 724f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if line.find("RELOC") != -1: 725f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch reloc_sections.add(after_section) 726f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch after_section = None 727f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 728f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 729f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch match = OBJDUMP_SECTION_HEADER_RE.match(line) 730f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if match: 731f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch after_section = match.group(1) 732f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 733f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 734f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if OBJDUMP_DYNAMIC_SYMBOLS_START_RE.match(line): 735f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch dynamic = True 736f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 737f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 738f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch match = OBJDUMP_SYMBOL_LINE_RE.match(line) 739f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if match: 740f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch start_address = int(match.group(1), 16) 741f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch origin_offset = start_address 742f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch flags = match.group(2) 743f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch section = match.group(3) 744f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if section in code_sections: 745f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if dynamic or section in reloc_sections: 746f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch start_address += mmap_info.addr 747f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch size = int(match.group(4), 16) 748f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch name = match.group(5) 749f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch origin = mmap_info.filename 750f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code_map.Add(Code(name, start_address, start_address + size, 751f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch origin, origin_offset)) 752f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch finally: 753f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch pipe.close() 754f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch assert process.wait() == 0, "Failed to objdump %s" % mmap_info.filename 755f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 756f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def Tick(self, pc): 757f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for i, mmap_info in enumerate(self.infos): 758f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if mmap_info.addr <= pc < (mmap_info.addr + mmap_info.len): 759f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_info.ticks += 1 760f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.infos[0], self.infos[i] = mmap_info, self.infos[0] 761f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return True 762f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return False 763f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 764f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def _UniqueMmapName(self, mmap_info): 765f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch name = mmap_info.filename 766f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch index = 1 767f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch while name in self.names: 768f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch name = "%s-%d" % (mmap_info.filename, index) 769f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch index += 1 770f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch self.names.add(name) 771f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return name 772f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 773f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch def _LoadKernelSymbols(self, code_map): 774f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not os.path.exists(KERNEL_ALLSYMS_FILE): 775f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print >>sys.stderr, "Warning: %s not found" % KERNEL_ALLSYMS_FILE 776f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return False 777f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch kallsyms = open(KERNEL_ALLSYMS_FILE, "r") 778f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = None 779f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for line in kallsyms: 780f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch match = KERNEL_ALLSYMS_LINE_RE.match(line) 781f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if match: 782f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch start_address = int(match.group(1), 16) 783f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch end_address = start_address 784f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch name = match.group(2) 785f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code: 786f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code.end_address = start_address 787f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code_map.Add(code, 16) 788f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = Code(name, start_address, end_address, "kernel", 0) 789f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch return True 790f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 791f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochdef PrintReport(code_map, library_repo, arch, ticks, options): 793f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "Ticks per symbol:" 794f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch used_code = [code for code in code_map.UsedCode()] 795f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch used_code.sort(key=lambda x: x.self_ticks, reverse=True) 796f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for i, code in enumerate(used_code): 797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code_ticks = code.self_ticks 798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch print "%10d %5.1f%% %s [%s]" % (code_ticks, 100. * code_ticks / ticks, 799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code.FullName(), code.origin) 800f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if options.disasm_all or i < options.disasm_top: 801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code.PrintAnnotated(arch, options) 802f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print 803f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "Ticks per library:" 804f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_infos = [m for m in library_repo.infos] 805f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_infos.sort(key=lambda m: m.ticks, reverse=True) 806f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for mmap_info in mmap_infos: 807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mmap_ticks = mmap_info.ticks 808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch print "%10d %5.1f%% %s" % (mmap_ticks, 100. * mmap_ticks / ticks, 809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch mmap_info.unique_name) 810f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 811f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 812f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochdef PrintDot(code_map, options): 813f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "digraph G {" 814f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for code in code_map.UsedCode(): 815f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code.self_ticks < 10: 816f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch continue 817f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "n%d [shape=box,label=\"%s\"];" % (code.id, code.name) 818f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code.callee_ticks: 819f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for callee, ticks in code.callee_ticks.iteritems(): 820f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "n%d -> n%d [label=\"%d\"];" % (code.id, callee.id, ticks) 821f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "}" 822f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 823f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 824f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochif __name__ == "__main__": 825f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser = optparse.OptionParser(USAGE) 826f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--snapshot-log", 827f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default="obj/release/snapshot.log", 828f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="V8 snapshot log file name [default: %default]") 829f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--log", 830f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default="v8.log", 831f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="V8 log file name [default: %default]") 832f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--snapshot", 833f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default=False, 834f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch action="store_true", 835f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="process V8 snapshot log [default: %default]") 836f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--trace", 837f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default="perf.data", 838f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="perf trace file name [default: %default]") 839f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--kernel", 840f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default=False, 841f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch action="store_true", 842f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="process kernel entries [default: %default]") 843f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--disasm-top", 844f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default=0, 845f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch type="int", 846f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help=("number of top symbols to disassemble and annotate " 847f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "[default: %default]")) 848f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--disasm-all", 849f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default=False, 850f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch action="store_true", 851f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help=("disassemble and annotate all used symbols " 852f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch "[default: %default]")) 853f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--dot", 854f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default=False, 855f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch action="store_true", 856f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="produce dot output (WIP) [default: %default]") 857f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch parser.add_option("--quiet", "-q", 858f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch default=False, 859f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch action="store_true", 860f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch help="no auxiliary messages [default: %default]") 861f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch options, args = parser.parse_args() 862f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 863f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not options.quiet: 864f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if options.snapshot: 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch print "V8 logs: %s, %s, %s.ll" % (options.snapshot_log, 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch options.log, 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch options.log) 868f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch print "V8 log: %s, %s.ll (no snapshot)" % (options.log, options.log) 870f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "Perf trace file: %s" % options.trace 871f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 872f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Stats. 873f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch events = 0 874f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks = 0 875f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch missed_ticks = 0 876f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch really_missed_ticks = 0 877f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_time = 0 878f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch sample_time = 0 879f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch # Process the snapshot log to fill the snapshot name map. 881f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch snapshot_name_map = {} 882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if options.snapshot: 883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch snapshot_log_reader = SnapshotLogReader(log_name=options.snapshot_log) 884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch snapshot_name_map = snapshot_log_reader.ReadNameMap() 885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch # Initialize the log reader. 887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code_map = CodeMap() 888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch log_reader = LogReader(log_name=options.log + ".ll", 889257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch code_map=code_map, 890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch snapshot_pos_to_name=snapshot_name_map) 891f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not options.quiet: 892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch print "Generated code architecture: %s" % log_reader.arch 893f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print 894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch sys.stdout.flush() 895f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 896f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch # Process the code and trace logs. 897f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch library_repo = LibraryRepo() 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch log_reader.ReadUpToGC() 899f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch trace_reader = TraceReader(options.trace) 900f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch while True: 901f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch header, offset = trace_reader.ReadEventHeader() 902f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not header: 903f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch break 904f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch events += 1 905f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if header.type == PERF_RECORD_MMAP: 906f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch start = time.time() 907f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_info = trace_reader.ReadMmap(header, offset) 908f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if mmap_info.filename == V8_GC_FAKE_MMAP: 909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch log_reader.ReadUpToGC() 910f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 911f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch library_repo.Load(mmap_info, code_map, options) 912f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch mmap_time += time.time() - start 913f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch elif header.type == PERF_RECORD_SAMPLE: 914f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch ticks += 1 915f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch start = time.time() 916f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch sample = trace_reader.ReadSample(header, offset) 917f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = code_map.Find(sample.ip) 918f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code: 919f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code.Tick(sample.ip) 920f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 921f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch missed_ticks += 1 922f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not library_repo.Tick(sample.ip) and not code: 923f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch really_missed_ticks += 1 924f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if trace_reader.callchain_supported: 925f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch for ip in sample.ips: 926f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch caller_code = code_map.Find(ip) 927f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if caller_code: 928f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if code: 929f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch caller_code.CalleeTick(code) 930f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch code = caller_code 931f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch sample_time += time.time() - start 932f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 933f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if options.dot: 934f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch PrintDot(code_map, options) 935f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch else: 936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintReport(code_map, library_repo, log_reader.arch, ticks, options) 937f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 938f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch if not options.quiet: 939f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print 940f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "Stats:" 941f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%10d total trace events" % events 942f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%10d total ticks" % ticks 943f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%10d ticks not in symbols" % missed_ticks 944f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%10d unaccounted ticks" % really_missed_ticks 945f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%10d total symbols" % len([c for c in code_map.AllCode()]) 946f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%10d used symbols" % len([c for c in code_map.UsedCode()]) 947f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%9.2fs library processing time" % mmap_time 948f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch print "%9.2fs tick processing time" % sample_time 949f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 950f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch log_reader.Dispose() 951f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch trace_reader.Dispose() 952