- add sources.
[platform/framework/web/crosswalk.git] / src / tools / ipc_messages_log.py
1 #!/usr/bin/python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """"Processes a log file and resolves IPC message identifiers.
7
8 Resolves IPC messages of the form [unknown type NNNNNN] to named IPC messages.
9
10 e.g. logfile containing
11
12 I/stderr  ( 3915): ipc 3915.3.1370207904 2147483647 S [unknown type 66372]
13
14 will be transformed to:
15
16 I/stderr  ( 3915): ipc 3915.3.1370207904 2147483647 S ViewMsg_SetCSSColors
17
18 In order to find the message header files efficiently, it requires that
19 Chromium is checked out using git.
20 """
21
22 import optparse
23 import os
24 import re
25 import subprocess
26 import sys
27
28
29 def _SourceDir():
30   """Get chromium's source directory."""
31   return os.path.join(sys.path[0], '..')
32
33
34 def _ReadLines(f):
35   """Read from file f and generate right-stripped lines."""
36   for line in f:
37     yield line.rstrip()
38
39
40 def _GetMsgStartTable():
41   """Read MsgStart enumeration from ipc/ipc_message_utils.h.
42
43   Determines the message type identifiers by reading.
44   header file ipc/ipc_message_utils.h and looking for
45   enum IPCMessageStart.  Assumes following code format in header file:
46   enum IPCMessageStart {
47      Type1MsgStart ...,
48      Type2MsgStart,
49   };
50
51   Returns:
52       A dictionary mapping StartName to enumeration value.
53   """
54   ipc_message_file = _SourceDir() + '/ipc/ipc_message_utils.h'
55   ipc_message_lines = _ReadLines(open(ipc_message_file))
56   is_msg_start = False
57   count = 0
58   msg_start_table = dict()
59   for line in ipc_message_lines:
60     if is_msg_start:
61       if line.strip() == '};':
62         break
63       msgstart_index = line.find('MsgStart')
64       msg_type = line[:msgstart_index] + 'MsgStart'
65       msg_start_table[msg_type.strip()] = count
66       count+=1
67     elif line.strip() == 'enum IPCMessageStart {':
68       is_msg_start = True
69
70   return msg_start_table
71
72
73 def _FindMessageHeaderFiles():
74   """Look through the source directory for *_messages.h."""
75   os.chdir(_SourceDir())
76   pipe = subprocess.Popen(['git', 'ls-files', '--', '*_messages.h'],
77                           stdout=subprocess.PIPE)
78   return _ReadLines(pipe.stdout)
79
80
81 def _GetMsgId(msg_start, line_number, msg_start_table):
82   """Construct the meessage id given the msg_start and the line number."""
83   hex_str = '%x%04x' % (msg_start_table[msg_start], line_number)
84   return int(hex_str, 16)
85
86
87 def _ReadHeaderFile(f, msg_start_table, msg_map):
88   """Read a header file and construct a map from message_id to message name."""
89   msg_def_re = re.compile(
90       '^IPC_(?:SYNC_)?MESSAGE_[A-Z0-9_]+\(([A-Za-z0-9_]+).*')
91   msg_start_re = re.compile(
92       '^\s*#define\s+IPC_MESSAGE_START\s+([a-zA-Z0-9_]+MsgStart).*')
93   msg_start = None
94   msg_name = None
95   line_number = 0
96
97   for line in f:
98     line_number+=1
99     match = re.match(msg_start_re, line)
100     if match:
101       msg_start = match.group(1)
102       # print "msg_start = " + msg_start
103     match = re.match(msg_def_re, line)
104     if match:
105       msg_name = match.group(1)
106       # print "msg_name = " + msg_name
107     if msg_start and msg_name:
108       msg_id = _GetMsgId(msg_start, line_number, msg_start_table)
109       msg_map[msg_id] = msg_name
110   return msg_map
111
112
113 def _ResolveMsg(msg_type, msg_map):
114   """Fully resolve a message type to a name."""
115   if msg_type in msg_map:
116     return msg_map[msg_type]
117   else:
118     return '[Unknown message %d (0x%x)]x' % (msg_type, msg_type)
119
120
121 def _ProcessLog(f, msg_map):
122   """Read lines from f and resolve the IPC messages according to msg_map."""
123   unknown_msg_re = re.compile('\[unknown type (\d+)\]')
124   for line in f:
125     line = line.rstrip()
126     match = re.search(unknown_msg_re, line)
127     if match:
128       line = re.sub(unknown_msg_re,
129                     _ResolveMsg(int(match.group(1)), msg_map),
130                     line)
131     print line
132
133
134 def _GetMsgMap():
135   """Returns a dictionary mapping from message number to message name."""
136   msg_start_table = _GetMsgStartTable()
137   msg_map = dict()
138   for header_file in _FindMessageHeaderFiles():
139     _ReadHeaderFile(open(header_file),
140                     msg_start_table,
141                     msg_map)
142   return msg_map
143
144
145 def main():
146   """Processes one or more log files with IPC logging messages.
147
148      Replaces '[unknown type NNNNNN]' with resolved
149      IPC messages.
150
151      Reads from standard input if no log files specified on the
152      command line.
153   """
154   parser = optparse.OptionParser('usage: %prog [LOGFILE...]')
155   (_, args) = parser.parse_args()
156
157   msg_map = _GetMsgMap()
158   log_files = args
159
160   if log_files:
161     for log_file in log_files:
162       _ProcessLog(open(log_file), msg_map)
163   else:
164     _ProcessLog(sys.stdin, msg_map)
165
166
167 if __name__ == '__main__':
168   main()