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