blob: eef60c03840fe0bc4dfc9f77bc4afc6fe5c53e84 [file] [log] [blame]
Daniel Leunga5ab1a72021-04-02 12:54:53 -07001#!/usr/bin/env python3
2#
3# Copyright (c) 2021 Intel Corporation
4#
5# SPDX-License-Identifier: Apache-2.0
6
7"""
8Log Parser for Dictionary-based Logging
9
10This uses the JSON database file to decode the input binary
11log data and print the log messages.
12"""
13
14import argparse
15import binascii
16import logging
17import sys
18
David Leachf5b0f922021-06-23 15:18:22 -050019import dictionary_parser
20from dictionary_parser.log_database import LogDatabase
Daniel Leunga5ab1a72021-04-02 12:54:53 -070021
22
23LOGGER_FORMAT = "%(message)s"
24logger = logging.getLogger("parser")
25
26LOG_HEX_SEP = "##ZLOGV1##"
27
28
29def parse_args():
30 """Parse command line arguments"""
Jamie McCraeec704442023-01-04 16:08:36 +000031 argparser = argparse.ArgumentParser(allow_abbrev=False)
Daniel Leunga5ab1a72021-04-02 12:54:53 -070032
33 argparser.add_argument("dbfile", help="Dictionary Logging Database file")
34 argparser.add_argument("logfile", help="Log Data file")
35 argparser.add_argument("--hex", action="store_true",
36 help="Log Data file is in hexadecimal strings")
37 argparser.add_argument("--rawhex", action="store_true",
38 help="Log file only contains hexadecimal log data")
39 argparser.add_argument("--debug", action="store_true",
40 help="Print extra debugging information")
41
42 return argparser.parse_args()
43
44
Daniel Leungdc6b51a2022-01-18 13:36:53 -080045def read_log_file(args):
46 """
47 Read the log from file
48 """
49 logdata = None
Daniel Leunga5ab1a72021-04-02 12:54:53 -070050
51 # Open log data file for reading
52 if args.hex:
53 if args.rawhex:
54 # Simply log file with only hexadecimal data
David Leachf5b0f922021-06-23 15:18:22 -050055 logdata = dictionary_parser.utils.convert_hex_file_to_bin(args.logfile)
Daniel Leunga5ab1a72021-04-02 12:54:53 -070056 else:
57 hexdata = ''
58
Daniel Leungdc6b51a2022-01-18 13:36:53 -080059 with open(args.logfile, "r", encoding="iso-8859-1") as hexfile:
Daniel Leunga5ab1a72021-04-02 12:54:53 -070060 for line in hexfile.readlines():
61 hexdata += line.strip()
62
63 if LOG_HEX_SEP not in hexdata:
64 logger.error("ERROR: Cannot find start of log data, exiting...")
65 sys.exit(1)
66
67 idx = hexdata.index(LOG_HEX_SEP) + len(LOG_HEX_SEP)
68 hexdata = hexdata[idx:]
69
70 if len(hexdata) % 2 != 0:
71 # Make sure there are even number of characters
72 idx = int(len(hexdata) / 2) * 2
73 hexdata = hexdata[:idx]
74
75 idx = 0
76 while idx < len(hexdata):
77 # When running QEMU via west or ninja, there may be additional
78 # strings printed by QEMU, west or ninja (for example, QEMU
79 # is terminated, or user interrupted, etc). So we need to
80 # figure out where the end of log data stream by
81 # trying to convert from hex to bin.
82 idx += 2
83
84 try:
85 binascii.unhexlify(hexdata[:idx])
86 except binascii.Error:
87 idx -= 2
88 break
89
90 logdata = binascii.unhexlify(hexdata[:idx])
91 else:
92 logfile = open(args.logfile, "rb")
93 if not logfile:
94 logger.error("ERROR: Cannot open binary log data file: %s, exiting...", args.logfile)
95 sys.exit(1)
96
97 logdata = logfile.read()
98
99 logfile.close()
100
Daniel Leungdc6b51a2022-01-18 13:36:53 -0800101 return logdata
102
103
104def main():
105 """Main function of log parser"""
106 args = parse_args()
107
108 # Setup logging for parser
109 logging.basicConfig(format=LOGGER_FORMAT)
110 if args.debug:
111 logger.setLevel(logging.DEBUG)
112 else:
113 logger.setLevel(logging.INFO)
114
115 # Read from database file
116 database = LogDatabase.read_json_database(args.dbfile)
117 if database is None:
118 logger.error("ERROR: Cannot open database file: %s, exiting...", args.dbfile)
119 sys.exit(1)
120
121 logdata = read_log_file(args)
122 if logdata is None:
123 logger.error("ERROR: cannot read log from file: %s, exiting...", args.logfile)
124 sys.exit(1)
125
David Leachf5b0f922021-06-23 15:18:22 -0500126 log_parser = dictionary_parser.get_parser(database)
Daniel Leunga5ab1a72021-04-02 12:54:53 -0700127 if log_parser is not None:
128 logger.debug("# Build ID: %s", database.get_build_id())
129 logger.debug("# Target: %s, %d-bit", database.get_arch(), database.get_tgt_bits())
130 if database.is_tgt_little_endian():
131 logger.debug("# Endianness: Little")
132 else:
133 logger.debug("# Endianness: Big")
134
135 ret = log_parser.parse_log_data(logdata, debug=args.debug)
136 if not ret:
137 logger.error("ERROR: there were error(s) parsing log data")
138 sys.exit(1)
139 else:
140 logger.error("ERROR: Cannot find a suitable parser matching database version!")
141 sys.exit(1)
142
143
144if __name__ == "__main__":
145 main()