123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- #!/usr/bin/env python
- # Copyright (c) 2012 The Chromium Authors. All rights reserved.
- # Use of this source code is governed by a BSD-style license that can be
- # found in the LICENSE file.
- """"Processes a log file and resolves IPC message identifiers.
- Resolves IPC messages of the form [unknown type NNNNNN] to named IPC messages.
- e.g. logfile containing
- I/stderr ( 3915): ipc 3915.3.1370207904 2147483647 S [unknown type 66372]
- will be transformed to:
- I/stderr ( 3915): ipc 3915.3.1370207904 2147483647 S ViewMsg_SetCSSColors
- In order to find the message header files efficiently, it requires that
- Chromium is checked out using git.
- """
- from __future__ import print_function
- import optparse
- import os
- import re
- import subprocess
- import sys
- def _SourceDir():
- """Get chromium's source directory."""
- return os.path.join(sys.path[0], '..')
- def _ReadLines(f):
- """Read from file f and generate right-stripped lines."""
- for line in f:
- yield line.rstrip()
- def _GetMsgStartTable():
- """Read MsgStart enumeration from ipc/ipc_message_utils.h.
- Determines the message type identifiers by reading.
- header file ipc/ipc_message_utils.h and looking for
- enum IPCMessageStart. Assumes following code format in header file:
- enum IPCMessageStart {
- Type1MsgStart ...,
- Type2MsgStart,
- };
- Returns:
- A dictionary mapping StartName to enumeration value.
- """
- ipc_message_file = _SourceDir() + '/ipc/ipc_message_utils.h'
- ipc_message_lines = _ReadLines(open(ipc_message_file))
- is_msg_start = False
- count = 0
- msg_start_table = dict()
- for line in ipc_message_lines:
- if is_msg_start:
- if line.strip() == '};':
- break
- msgstart_index = line.find('MsgStart')
- msg_type = line[:msgstart_index] + 'MsgStart'
- msg_start_table[msg_type.strip()] = count
- count+=1
- elif line.strip() == 'enum IPCMessageStart {':
- is_msg_start = True
- return msg_start_table
- def _FindMessageHeaderFiles():
- """Look through the source directory for *_messages.h."""
- os.chdir(_SourceDir())
- pipe = subprocess.Popen(['git', 'ls-files', '--', '*_messages.h'],
- stdout=subprocess.PIPE)
- return _ReadLines(pipe.stdout)
- def _GetMsgId(msg_start, line_number, msg_start_table):
- """Construct the meessage id given the msg_start and the line number."""
- hex_str = '%x%04x' % (msg_start_table[msg_start], line_number)
- return int(hex_str, 16)
- def _ReadHeaderFile(f, msg_start_table, msg_map):
- """Read a header file and construct a map from message_id to message name."""
- msg_def_re = re.compile(
- '^IPC_(?:SYNC_)?MESSAGE_[A-Z0-9_]+\(([A-Za-z0-9_]+).*')
- msg_start_re = re.compile(
- '^\s*#define\s+IPC_MESSAGE_START\s+([a-zA-Z0-9_]+MsgStart).*')
- msg_start = None
- msg_name = None
- line_number = 0
- for line in f:
- line_number+=1
- match = re.match(msg_start_re, line)
- if match:
- msg_start = match.group(1)
- # print("msg_start = " + msg_start)
- match = re.match(msg_def_re, line)
- if match:
- msg_name = match.group(1)
- # print("msg_name = " + msg_name)
- if msg_start and msg_name:
- msg_id = _GetMsgId(msg_start, line_number, msg_start_table)
- msg_map[msg_id] = msg_name
- return msg_map
- def _ResolveMsg(msg_type, msg_map):
- """Fully resolve a message type to a name."""
- if msg_type in msg_map:
- return msg_map[msg_type]
- else:
- return '[Unknown message %d (0x%x)]x' % (msg_type, msg_type)
- def _ProcessLog(f, msg_map):
- """Read lines from f and resolve the IPC messages according to msg_map."""
- unknown_msg_re = re.compile('\[unknown type (\d+)\]')
- for line in f:
- line = line.rstrip()
- match = re.search(unknown_msg_re, line)
- if match:
- line = re.sub(unknown_msg_re,
- _ResolveMsg(int(match.group(1)), msg_map),
- line)
- print(line)
- def _GetMsgMap():
- """Returns a dictionary mapping from message number to message name."""
- msg_start_table = _GetMsgStartTable()
- msg_map = dict()
- for header_file in _FindMessageHeaderFiles():
- _ReadHeaderFile(open(header_file),
- msg_start_table,
- msg_map)
- return msg_map
- def main():
- """Processes one or more log files with IPC logging messages.
- Replaces '[unknown type NNNNNN]' with resolved
- IPC messages.
- Reads from standard input if no log files specified on the
- command line.
- """
- parser = optparse.OptionParser('usage: %prog [LOGFILE...]')
- (_, args) = parser.parse_args()
- msg_map = _GetMsgMap()
- log_files = args
- if log_files:
- for log_file in log_files:
- _ProcessLog(open(log_file), msg_map)
- else:
- _ProcessLog(sys.stdin, msg_map)
- if __name__ == '__main__':
- main()
|