13d004a37SPhilippe Mathieu-Daudé#!/usr/bin/env python3 2821c1130SAlex Bennée# -*- coding: utf-8 -*- 3821c1130SAlex Bennée# 4821c1130SAlex Bennée# Dump the contents of a recorded execution stream 5821c1130SAlex Bennée# 649ebe9b1SAlex Bennée# Copyright (c) 2017 Alex Bennée <alex.bennee@linaro.org> 7821c1130SAlex Bennée# 8821c1130SAlex Bennée# This library is free software; you can redistribute it and/or 9821c1130SAlex Bennée# modify it under the terms of the GNU Lesser General Public 10821c1130SAlex Bennée# License as published by the Free Software Foundation; either 1161f3c91aSChetan Pant# version 2.1 of the License, or (at your option) any later version. 12821c1130SAlex Bennée# 13821c1130SAlex Bennée# This library is distributed in the hope that it will be useful, 14821c1130SAlex Bennée# but WITHOUT ANY WARRANTY; without even the implied warranty of 15821c1130SAlex Bennée# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16821c1130SAlex Bennée# Lesser General Public License for more details. 17821c1130SAlex Bennée# 18821c1130SAlex Bennée# You should have received a copy of the GNU Lesser General Public 19821c1130SAlex Bennée# License along with this library; if not, see <http://www.gnu.org/licenses/>. 20821c1130SAlex Bennée 21821c1130SAlex Bennéeimport argparse 22821c1130SAlex Bennéeimport struct 23821c1130SAlex Bennéefrom collections import namedtuple 24821c1130SAlex Bennée 25821c1130SAlex Bennée# This mirrors some of the global replay state which some of the 26821c1130SAlex Bennée# stream loading refers to. Some decoders may read the next event so 27821c1130SAlex Bennée# we need handle that case. Calling reuse_event will ensure the next 28821c1130SAlex Bennée# event is read from the cache rather than advancing the file. 29821c1130SAlex Bennée 30821c1130SAlex Bennéeclass ReplayState(object): 31821c1130SAlex Bennée def __init__(self): 32821c1130SAlex Bennée self.event = -1 33821c1130SAlex Bennée self.event_count = 0 34821c1130SAlex Bennée self.already_read = False 35821c1130SAlex Bennée self.current_checkpoint = 0 36821c1130SAlex Bennée self.checkpoint = 0 37821c1130SAlex Bennée 38821c1130SAlex Bennée def set_event(self, ev): 39821c1130SAlex Bennée self.event = ev 40821c1130SAlex Bennée self.event_count += 1 41821c1130SAlex Bennée 42821c1130SAlex Bennée def get_event(self): 43821c1130SAlex Bennée self.already_read = False 44821c1130SAlex Bennée return self.event 45821c1130SAlex Bennée 46821c1130SAlex Bennée def reuse_event(self, ev): 47821c1130SAlex Bennée self.event = ev 48821c1130SAlex Bennée self.already_read = True 49821c1130SAlex Bennée 50821c1130SAlex Bennée def set_checkpoint(self): 51821c1130SAlex Bennée self.checkpoint = self.event - self.checkpoint_start 52821c1130SAlex Bennée 53821c1130SAlex Bennée def get_checkpoint(self): 54821c1130SAlex Bennée return self.checkpoint 55821c1130SAlex Bennée 56821c1130SAlex Bennéereplay_state = ReplayState() 57821c1130SAlex Bennée 58821c1130SAlex Bennée# Simple read functions that mirror replay-internal.c 59821c1130SAlex Bennée# The file-stream is big-endian and manually written out a byte at a time. 60821c1130SAlex Bennée 61821c1130SAlex Bennéedef read_byte(fin): 62821c1130SAlex Bennée "Read a single byte" 63821c1130SAlex Bennée return struct.unpack('>B', fin.read(1))[0] 64821c1130SAlex Bennée 65821c1130SAlex Bennéedef read_event(fin): 66821c1130SAlex Bennée "Read a single byte event, but save some state" 67821c1130SAlex Bennée if replay_state.already_read: 68821c1130SAlex Bennée return replay_state.get_event() 69821c1130SAlex Bennée else: 70821c1130SAlex Bennée replay_state.set_event(read_byte(fin)) 71821c1130SAlex Bennée return replay_state.event 72821c1130SAlex Bennée 73821c1130SAlex Bennéedef read_word(fin): 74821c1130SAlex Bennée "Read a 16 bit word" 75821c1130SAlex Bennée return struct.unpack('>H', fin.read(2))[0] 76821c1130SAlex Bennée 77821c1130SAlex Bennéedef read_dword(fin): 78821c1130SAlex Bennée "Read a 32 bit word" 79821c1130SAlex Bennée return struct.unpack('>I', fin.read(4))[0] 80821c1130SAlex Bennée 81821c1130SAlex Bennéedef read_qword(fin): 82821c1130SAlex Bennée "Read a 64 bit word" 83821c1130SAlex Bennée return struct.unpack('>Q', fin.read(8))[0] 84821c1130SAlex Bennée 85821c1130SAlex Bennée# Generic decoder structure 86821c1130SAlex BennéeDecoder = namedtuple("Decoder", "eid name fn") 87821c1130SAlex Bennée 88821c1130SAlex Bennéedef call_decode(table, index, dumpfile): 89821c1130SAlex Bennée "Search decode table for next step" 90821c1130SAlex Bennée decoder = next((d for d in table if d.eid == index), None) 91821c1130SAlex Bennée if not decoder: 92f03868bdSEduardo Habkost print("Could not decode index: %d" % (index)) 93f03868bdSEduardo Habkost print("Entry is: %s" % (decoder)) 94f03868bdSEduardo Habkost print("Decode Table is:\n%s" % (table)) 95821c1130SAlex Bennée return False 96821c1130SAlex Bennée else: 97821c1130SAlex Bennée return decoder.fn(decoder.eid, decoder.name, dumpfile) 98821c1130SAlex Bennée 99821c1130SAlex Bennée# Print event 100821c1130SAlex Bennéedef print_event(eid, name, string=None, event_count=None): 101821c1130SAlex Bennée "Print event with count" 102821c1130SAlex Bennée if not event_count: 103821c1130SAlex Bennée event_count = replay_state.event_count 104821c1130SAlex Bennée 105821c1130SAlex Bennée if string: 106f03868bdSEduardo Habkost print("%d:%s(%d) %s" % (event_count, name, eid, string)) 107821c1130SAlex Bennée else: 108f03868bdSEduardo Habkost print("%d:%s(%d)" % (event_count, name, eid)) 109821c1130SAlex Bennée 110821c1130SAlex Bennée 111821c1130SAlex Bennée# Decoders for each event type 112821c1130SAlex Bennée 113821c1130SAlex Bennéedef decode_unimp(eid, name, _unused_dumpfile): 114*d30b5bc9SMichael Tokarev "Unimplemented decoder, will trigger exit" 115f03868bdSEduardo Habkost print("%s not handled - will now stop" % (name)) 116821c1130SAlex Bennée return False 117821c1130SAlex Bennée 118821c1130SAlex Bennée# Checkpoint decoder 119821c1130SAlex Bennéedef swallow_async_qword(eid, name, dumpfile): 120821c1130SAlex Bennée "Swallow a qword of data without looking at it" 121821c1130SAlex Bennée step_id = read_qword(dumpfile) 122f03868bdSEduardo Habkost print(" %s(%d) @ %d" % (name, eid, step_id)) 123821c1130SAlex Bennée return True 124821c1130SAlex Bennée 125821c1130SAlex Bennéeasync_decode_table = [ Decoder(0, "REPLAY_ASYNC_EVENT_BH", swallow_async_qword), 126821c1130SAlex Bennée Decoder(1, "REPLAY_ASYNC_INPUT", decode_unimp), 127821c1130SAlex Bennée Decoder(2, "REPLAY_ASYNC_INPUT_SYNC", decode_unimp), 128821c1130SAlex Bennée Decoder(3, "REPLAY_ASYNC_CHAR_READ", decode_unimp), 129821c1130SAlex Bennée Decoder(4, "REPLAY_ASYNC_EVENT_BLOCK", decode_unimp), 130821c1130SAlex Bennée Decoder(5, "REPLAY_ASYNC_EVENT_NET", decode_unimp), 131821c1130SAlex Bennée] 132821c1130SAlex Bennée# See replay_read_events/replay_read_event 133821c1130SAlex Bennéedef decode_async(eid, name, dumpfile): 134821c1130SAlex Bennée """Decode an ASYNC event""" 135821c1130SAlex Bennée 136821c1130SAlex Bennée print_event(eid, name) 137821c1130SAlex Bennée 138821c1130SAlex Bennée async_event_kind = read_byte(dumpfile) 139821c1130SAlex Bennée async_event_checkpoint = read_byte(dumpfile) 140821c1130SAlex Bennée 141821c1130SAlex Bennée if async_event_checkpoint != replay_state.current_checkpoint: 142f03868bdSEduardo Habkost print(" mismatch between checkpoint %d and async data %d" % ( 143f03868bdSEduardo Habkost replay_state.current_checkpoint, async_event_checkpoint)) 144821c1130SAlex Bennée return True 145821c1130SAlex Bennée 146821c1130SAlex Bennée return call_decode(async_decode_table, async_event_kind, dumpfile) 147821c1130SAlex Bennée 148821c1130SAlex Bennée 149821c1130SAlex Bennéedef decode_instruction(eid, name, dumpfile): 150821c1130SAlex Bennée ins_diff = read_dword(dumpfile) 151821c1130SAlex Bennée print_event(eid, name, "0x%x" % (ins_diff)) 152821c1130SAlex Bennée return True 153821c1130SAlex Bennée 154821c1130SAlex Bennéedef decode_audio_out(eid, name, dumpfile): 155821c1130SAlex Bennée audio_data = read_dword(dumpfile) 156821c1130SAlex Bennée print_event(eid, name, "%d" % (audio_data)) 157821c1130SAlex Bennée return True 158821c1130SAlex Bennée 159821c1130SAlex Bennéedef decode_checkpoint(eid, name, dumpfile): 160821c1130SAlex Bennée """Decode a checkpoint. 161821c1130SAlex Bennée 162821c1130SAlex Bennée Checkpoints contain a series of async events with their own specific data. 163821c1130SAlex Bennée """ 164821c1130SAlex Bennée replay_state.set_checkpoint() 165821c1130SAlex Bennée # save event count as we peek ahead 166821c1130SAlex Bennée event_number = replay_state.event_count 167821c1130SAlex Bennée next_event = read_event(dumpfile) 168821c1130SAlex Bennée 169821c1130SAlex Bennée # if the next event is EVENT_ASYNC there are a bunch of 170821c1130SAlex Bennée # async events to read, otherwise we are done 171821c1130SAlex Bennée if next_event != 3: 172821c1130SAlex Bennée print_event(eid, name, "no additional data", event_number) 173821c1130SAlex Bennée else: 174821c1130SAlex Bennée print_event(eid, name, "more data follows", event_number) 175821c1130SAlex Bennée 176821c1130SAlex Bennée replay_state.reuse_event(next_event) 177821c1130SAlex Bennée return True 178821c1130SAlex Bennée 179821c1130SAlex Bennéedef decode_checkpoint_init(eid, name, dumpfile): 180821c1130SAlex Bennée print_event(eid, name) 181821c1130SAlex Bennée return True 182821c1130SAlex Bennée 183821c1130SAlex Bennéedef decode_interrupt(eid, name, dumpfile): 184821c1130SAlex Bennée print_event(eid, name) 185821c1130SAlex Bennée return True 186821c1130SAlex Bennée 187821c1130SAlex Bennéedef decode_clock(eid, name, dumpfile): 188821c1130SAlex Bennée clock_data = read_qword(dumpfile) 189821c1130SAlex Bennée print_event(eid, name, "0x%x" % (clock_data)) 190821c1130SAlex Bennée return True 191821c1130SAlex Bennée 192821c1130SAlex Bennée 193821c1130SAlex Bennée# pre-MTTCG merge 194821c1130SAlex Bennéev5_event_table = [Decoder(0, "EVENT_INSTRUCTION", decode_instruction), 195821c1130SAlex Bennée Decoder(1, "EVENT_INTERRUPT", decode_interrupt), 196821c1130SAlex Bennée Decoder(2, "EVENT_EXCEPTION", decode_unimp), 197821c1130SAlex Bennée Decoder(3, "EVENT_ASYNC", decode_async), 198821c1130SAlex Bennée Decoder(4, "EVENT_SHUTDOWN", decode_unimp), 199821c1130SAlex Bennée Decoder(5, "EVENT_CHAR_WRITE", decode_unimp), 200821c1130SAlex Bennée Decoder(6, "EVENT_CHAR_READ_ALL", decode_unimp), 201821c1130SAlex Bennée Decoder(7, "EVENT_CHAR_READ_ALL_ERROR", decode_unimp), 202821c1130SAlex Bennée Decoder(8, "EVENT_CLOCK_HOST", decode_clock), 203821c1130SAlex Bennée Decoder(9, "EVENT_CLOCK_VIRTUAL_RT", decode_clock), 204821c1130SAlex Bennée Decoder(10, "EVENT_CP_CLOCK_WARP_START", decode_checkpoint), 205821c1130SAlex Bennée Decoder(11, "EVENT_CP_CLOCK_WARP_ACCOUNT", decode_checkpoint), 206821c1130SAlex Bennée Decoder(12, "EVENT_CP_RESET_REQUESTED", decode_checkpoint), 207821c1130SAlex Bennée Decoder(13, "EVENT_CP_SUSPEND_REQUESTED", decode_checkpoint), 208821c1130SAlex Bennée Decoder(14, "EVENT_CP_CLOCK_VIRTUAL", decode_checkpoint), 209821c1130SAlex Bennée Decoder(15, "EVENT_CP_CLOCK_HOST", decode_checkpoint), 210821c1130SAlex Bennée Decoder(16, "EVENT_CP_CLOCK_VIRTUAL_RT", decode_checkpoint), 211821c1130SAlex Bennée Decoder(17, "EVENT_CP_INIT", decode_checkpoint_init), 212821c1130SAlex Bennée Decoder(18, "EVENT_CP_RESET", decode_checkpoint), 213821c1130SAlex Bennée] 214821c1130SAlex Bennée 215821c1130SAlex Bennée# post-MTTCG merge, AUDIO support added 216821c1130SAlex Bennéev6_event_table = [Decoder(0, "EVENT_INSTRUCTION", decode_instruction), 217821c1130SAlex Bennée Decoder(1, "EVENT_INTERRUPT", decode_interrupt), 218821c1130SAlex Bennée Decoder(2, "EVENT_EXCEPTION", decode_unimp), 219821c1130SAlex Bennée Decoder(3, "EVENT_ASYNC", decode_async), 220821c1130SAlex Bennée Decoder(4, "EVENT_SHUTDOWN", decode_unimp), 221821c1130SAlex Bennée Decoder(5, "EVENT_CHAR_WRITE", decode_unimp), 222821c1130SAlex Bennée Decoder(6, "EVENT_CHAR_READ_ALL", decode_unimp), 223821c1130SAlex Bennée Decoder(7, "EVENT_CHAR_READ_ALL_ERROR", decode_unimp), 224821c1130SAlex Bennée Decoder(8, "EVENT_AUDIO_OUT", decode_audio_out), 225821c1130SAlex Bennée Decoder(9, "EVENT_AUDIO_IN", decode_unimp), 226821c1130SAlex Bennée Decoder(10, "EVENT_CLOCK_HOST", decode_clock), 227821c1130SAlex Bennée Decoder(11, "EVENT_CLOCK_VIRTUAL_RT", decode_clock), 228821c1130SAlex Bennée Decoder(12, "EVENT_CP_CLOCK_WARP_START", decode_checkpoint), 229821c1130SAlex Bennée Decoder(13, "EVENT_CP_CLOCK_WARP_ACCOUNT", decode_checkpoint), 230821c1130SAlex Bennée Decoder(14, "EVENT_CP_RESET_REQUESTED", decode_checkpoint), 231821c1130SAlex Bennée Decoder(15, "EVENT_CP_SUSPEND_REQUESTED", decode_checkpoint), 232821c1130SAlex Bennée Decoder(16, "EVENT_CP_CLOCK_VIRTUAL", decode_checkpoint), 233821c1130SAlex Bennée Decoder(17, "EVENT_CP_CLOCK_HOST", decode_checkpoint), 234821c1130SAlex Bennée Decoder(18, "EVENT_CP_CLOCK_VIRTUAL_RT", decode_checkpoint), 235821c1130SAlex Bennée Decoder(19, "EVENT_CP_INIT", decode_checkpoint_init), 236821c1130SAlex Bennée Decoder(20, "EVENT_CP_RESET", decode_checkpoint), 237821c1130SAlex Bennée] 238821c1130SAlex Bennée 239821c1130SAlex Bennée# Shutdown cause added 240821c1130SAlex Bennéev7_event_table = [Decoder(0, "EVENT_INSTRUCTION", decode_instruction), 241821c1130SAlex Bennée Decoder(1, "EVENT_INTERRUPT", decode_interrupt), 242821c1130SAlex Bennée Decoder(2, "EVENT_EXCEPTION", decode_unimp), 243821c1130SAlex Bennée Decoder(3, "EVENT_ASYNC", decode_async), 244821c1130SAlex Bennée Decoder(4, "EVENT_SHUTDOWN", decode_unimp), 245821c1130SAlex Bennée Decoder(5, "EVENT_SHUTDOWN_HOST_ERR", decode_unimp), 246821c1130SAlex Bennée Decoder(6, "EVENT_SHUTDOWN_HOST_QMP", decode_unimp), 247821c1130SAlex Bennée Decoder(7, "EVENT_SHUTDOWN_HOST_SIGNAL", decode_unimp), 248821c1130SAlex Bennée Decoder(8, "EVENT_SHUTDOWN_HOST_UI", decode_unimp), 249821c1130SAlex Bennée Decoder(9, "EVENT_SHUTDOWN_GUEST_SHUTDOWN", decode_unimp), 250821c1130SAlex Bennée Decoder(10, "EVENT_SHUTDOWN_GUEST_RESET", decode_unimp), 251821c1130SAlex Bennée Decoder(11, "EVENT_SHUTDOWN_GUEST_PANIC", decode_unimp), 252821c1130SAlex Bennée Decoder(12, "EVENT_SHUTDOWN___MAX", decode_unimp), 253821c1130SAlex Bennée Decoder(13, "EVENT_CHAR_WRITE", decode_unimp), 254821c1130SAlex Bennée Decoder(14, "EVENT_CHAR_READ_ALL", decode_unimp), 255821c1130SAlex Bennée Decoder(15, "EVENT_CHAR_READ_ALL_ERROR", decode_unimp), 256821c1130SAlex Bennée Decoder(16, "EVENT_AUDIO_OUT", decode_audio_out), 257821c1130SAlex Bennée Decoder(17, "EVENT_AUDIO_IN", decode_unimp), 258821c1130SAlex Bennée Decoder(18, "EVENT_CLOCK_HOST", decode_clock), 259821c1130SAlex Bennée Decoder(19, "EVENT_CLOCK_VIRTUAL_RT", decode_clock), 260821c1130SAlex Bennée Decoder(20, "EVENT_CP_CLOCK_WARP_START", decode_checkpoint), 261821c1130SAlex Bennée Decoder(21, "EVENT_CP_CLOCK_WARP_ACCOUNT", decode_checkpoint), 262821c1130SAlex Bennée Decoder(22, "EVENT_CP_RESET_REQUESTED", decode_checkpoint), 263821c1130SAlex Bennée Decoder(23, "EVENT_CP_SUSPEND_REQUESTED", decode_checkpoint), 264821c1130SAlex Bennée Decoder(24, "EVENT_CP_CLOCK_VIRTUAL", decode_checkpoint), 265821c1130SAlex Bennée Decoder(25, "EVENT_CP_CLOCK_HOST", decode_checkpoint), 266821c1130SAlex Bennée Decoder(26, "EVENT_CP_CLOCK_VIRTUAL_RT", decode_checkpoint), 267821c1130SAlex Bennée Decoder(27, "EVENT_CP_INIT", decode_checkpoint_init), 268821c1130SAlex Bennée Decoder(28, "EVENT_CP_RESET", decode_checkpoint), 269821c1130SAlex Bennée] 270821c1130SAlex Bennée 271821c1130SAlex Bennéedef parse_arguments(): 272821c1130SAlex Bennée "Grab arguments for script" 273821c1130SAlex Bennée parser = argparse.ArgumentParser() 274821c1130SAlex Bennée parser.add_argument("-f", "--file", help='record/replay dump to read from', 275821c1130SAlex Bennée required=True) 276821c1130SAlex Bennée return parser.parse_args() 277821c1130SAlex Bennée 278821c1130SAlex Bennéedef decode_file(filename): 279821c1130SAlex Bennée "Decode a record/replay dump" 280821c1130SAlex Bennée dumpfile = open(filename, "rb") 281821c1130SAlex Bennée 282821c1130SAlex Bennée # read and throwaway the header 283821c1130SAlex Bennée version = read_dword(dumpfile) 284821c1130SAlex Bennée junk = read_qword(dumpfile) 285821c1130SAlex Bennée 286f03868bdSEduardo Habkost print("HEADER: version 0x%x" % (version)) 287821c1130SAlex Bennée 288821c1130SAlex Bennée if version == 0xe02007: 289821c1130SAlex Bennée event_decode_table = v7_event_table 290821c1130SAlex Bennée replay_state.checkpoint_start = 12 291821c1130SAlex Bennée elif version == 0xe02006: 292821c1130SAlex Bennée event_decode_table = v6_event_table 293821c1130SAlex Bennée replay_state.checkpoint_start = 12 294821c1130SAlex Bennée else: 295821c1130SAlex Bennée event_decode_table = v5_event_table 296821c1130SAlex Bennée replay_state.checkpoint_start = 10 297821c1130SAlex Bennée 298821c1130SAlex Bennée try: 299821c1130SAlex Bennée decode_ok = True 300821c1130SAlex Bennée while decode_ok: 301821c1130SAlex Bennée event = read_event(dumpfile) 302821c1130SAlex Bennée decode_ok = call_decode(event_decode_table, event, dumpfile) 303821c1130SAlex Bennée finally: 304821c1130SAlex Bennée dumpfile.close() 305821c1130SAlex Bennée 306821c1130SAlex Bennéeif __name__ == "__main__": 307821c1130SAlex Bennée args = parse_arguments() 308821c1130SAlex Bennée decode_file(args.file) 309