diff --git a/dcc_parser/sysregs_parser_minidump.py b/dcc_parser/sysregs_parser_minidump.py new file mode 100644 index 0000000000000000000000000000000000000000..ab8b841bb89054c55b612b324b3cb8071ee9b957 --- /dev/null +++ b/dcc_parser/sysregs_parser_minidump.py @@ -0,0 +1,176 @@ +# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 and +# only version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +import datetime +import logging +import logging.handlers +import os +import struct +import sys + +from optparse import OptionParser + +count = 0 +address = [] +data = [] + +def log_init(name, path, filename): + # Set up logger + logger = logging.getLogger(name) + logger.setLevel(logging.INFO) + + # Add the log message handler to the logger + if filename is not None: + handler = logging.FileHandler(path + '/' + filename, mode='w') + else: + handler = logging.StreamHandler(sys.stdout) + + logger.addHandler(handler) + return logger + +def read_data(data_pt): + nr = count + flag = 1 + while nr > 0: + word = data_pt.read(4) + if len(word) != 4: + break + + val = struct.unpack('<L', word)[0] + if flag % 2 != 0: + address.append(val) + else: + data.append(val) + flag = flag + 1 + nr = nr - 1 + return nr + +def read_config(config_pt): + while True: + word = config_pt.read(4) + if len(word) != 4: + break + + val = struct.unpack('<L', word)[0] + + if val == 0: + break + return val + +def dump_regs_json(options): + log.info("Dumping regs in JSON format in \'{0}\' file.".format(options.outfile)) + parsed_data.info("{") + parsed_data.info("\t\"version\": 1,") + parsed_data.info("\t\"timestamp\": \"{0}\",".format(datetime.date.today().strftime('%m/%d/%y'))) + parsed_data.info("\t\"generator\": \"Linux DCC Parser\",") + parsed_data.info("\t\"chip\": {") + parsed_data.info("\t\t\"name\": \"{0}\",".format(options.chipname)) + parsed_data.info("\t\t\"version\": \"{0}\"".format(options.chipversion)) + parsed_data.info("\t},") + parsed_data.info("\t\"registers\": [") + for addr, val in zip(address, data): + parsed_data.info("\t\t{{ \"address\": \"0x{0:08x}\", \"value\": \"0x{1:08x}\" }},".format(addr, val)) + parsed_data.info("\t]") + parsed_data.info("}") + return + +def dump_regs_xml(options): + print "dumping xml file" + log.info("Dumping regs in XML format in \'{0}\' file.".format(options.outfile)) + parsed_data.info("<?xml version=\"1.0\" encoding=\"utf-8\"?>") + parsed_data.info("<hwioDump version=\"1\"") + parsed_data.info("\t<timestamp>{0}</timestamp>".format(datetime.date.today().strftime('%m/%d/%y'))) + parsed_data.info("\t<generator>Linux DCC Parser</generator>") + parsed_data.info("\t<chip name=\"{0}\" version=\"{1}\">".format(options.chipname, options.chipversion)) + for addr, val in zip(address, data): + parsed_data.info("\t\t<register address=\"0x{0:08x}\" value=\"0x{1:08x}\" />".format(addr, val)) + parsed_data.info("\t</chip>") + parsed_data.info("</hwioDump>") + return + +def dump_regs(options): + if options.json is True: + dump_regs_json(options) + else: + dump_regs_xml(options) + +if __name__ == '__main__': + usage = 'usage: %prog [options to print]. Run with --help for more details' + parser = OptionParser(usage) + parser.add_option('-s', '--sysreg-file', dest='sysregfile', + help='sram image path') + parser.add_option('-j', '--json', action='store_true', + help='output in JSON format') + parser.add_option('-o', '--out-dir', dest='outdir', help='output dir path') + parser.add_option('-f', '--output-file', dest='outfile', + help='output filename') + parser.add_option('-l', '--log-file', dest='logfile', help='Log filename') + parser.add_option('', '--chip-name', dest='chipname', help='chip name') + parser.add_option('', '--chip-version', dest='chipversion', + help='chip version') + + (options, args) = parser.parse_args() + + print "sysregs_parser_invoked" + + args = '' + for arg in sys.argv: + args = args + arg + ' ' + + if options.outdir: + if not os.path.exists(options.outdir): + print ('!!! Out directory does not exist. Creating...') + try: + os.makedirs(options.outdir) + except: + print ("Failed to create %s. You probably don't have permissions there. Bailing." % options.outdir) + sys.exit(1) + else: + options.outdir = '.' + + if options.json: + ext = '.json' + else: + ext = '.xml' + + if options.outfile is None: + options.outfile = 'dcc_captured_data_minidump{0}'.format(ext) + + log = log_init('LOG', options.outdir, options.logfile) + + log.info("Data Capture and Compare(sysregs) parser.") + + if options.sysregfile is None: + log.error("No SRAM image file given! Exiting...") + parser.print_usage() + sys.exit(1) + + try: + sysreg_file = open(options.sysregfile, 'rb') + except: + log.error("could not open path {0}".format(options.sysregfile)) + log.error("Do you have read permissions on the path?") + sys.exit(1) + + count = 0 + count = read_config(sysreg_file) + if count == 0: + log.error('No configuration found in sysdbg_regs!!') + sys.exit(1) + + if read_data(sysreg_file): + log.error('Couldn\'t read complete data.') + else: + parsed_data = log_init('PARSED_DATA', options.outdir, options.outfile) + dump_regs(options) + + sysreg_file.close() + sys.stderr.flush() diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py index bb0616afbf7a36c5c60c9bc88215ff1e83f0d98f..b603209c3ce2e83098f6cc8578e75ca6104b75bb 100644 --- a/linux-ramdump-parser-v2/debug_image_v2.py +++ b/linux-ramdump-parser-v2/debug_image_v2.py @@ -29,6 +29,7 @@ from watchdog_v2 import TZRegDump_v2 from cachedumplib import lookup_cache_type from tlbdumplib import lookup_tlb_type from vsens import VsensData +from sysregs import SysRegDump MEMDUMPV2_MAGIC = 0x42445953 MAX_NUM_ENTRIES = 0x150 @@ -45,6 +46,7 @@ class client(object): MSM_DUMP_DATA_L3_CACHE = 0xD0 MSM_DUMP_DATA_OCMEM = 0xE0 MSM_DUMP_DATA_DBGUI_REG = 0xE5 + MSM_DUMP_DATA_MISC = 0xE8 MSM_DUMP_DATA_VSENSE = 0xE9 MSM_DUMP_DATA_TMC_ETF = 0xF0 MSM_DUMP_DATA_TMC_REG = 0x100 @@ -78,6 +80,7 @@ client_types = [ ('MSM_DUMP_DATA_TMC_REG', 'parse_qdss_common'), ('MSM_DUMP_DATA_L2_TLB', 'parse_l2_tlb'), ('MSM_DUMP_DATA_LLC_CACHE', 'parse_system_cache_common'), + ('MSM_DUMP_DATA_MISC', 'parse_sysdbg_regs'), ] qdss_tag_to_field_name = { @@ -101,7 +104,8 @@ minidump_dump_table_type = [ ('MSM_DUMP_DATA_DCC_REG', 'KDCC_REG'), ('MSM_DUMP_DATA_DCC_SRAM', 'KDCC_SRAM'), ('MSM_DUMP_DATA_TMC_ETF', 'KTMC_ETF'), - ('MSM_DUMP_DATA_TMC_REG', 'KTMC_REG') + ('MSM_DUMP_DATA_TMC_REG', 'KTMC_REG'), + ('MSM_DUMP_DATA_MISC', 'KMISC') ] @@ -205,6 +209,19 @@ class DebugImage_v2(): ram_dump.dcc = True return + def parse_sysdbg_regs(self, version, start, end, client_id, ram_dump): + client_name = self.dump_data_id_lookup_table[client_id] + + print_out_str( + 'Parsing {0} context start {1:x} end {2:x}'.format(client_name, start, end)) + + sysregs = SysRegDump(start, end) + if sysregs.dump_sysreg_img(ram_dump) is False: + print_out_str('!!! Could not dump sysdbg_regs') + else: + ram_dump.sysreg = True + return + def parse_vsens(self, version, start, end, client_id, ram_dump): client_name = self.dump_data_id_lookup_table[client_id] @@ -470,6 +487,28 @@ class DebugImage_v2(): print_out_str('--------') print_out_str(p.communicate()[0]) + def parse_sysreg(self,ram_dump): + out_dir = ram_dump.outdir + sysreg_parser_path_minidump = os.path.join(os.path.dirname(__file__), '..', 'dcc_parser', + 'sysregs_parser_minidump.py') + if sysreg_parser_path_minidump is None: + print_out_str("!!! Incorrect path for SYSREG specified.") + return + if not os.path.exists(sysreg_parser_path_minidump): + print_out_str("!!! sysreg_parser_path_minidump {0} does not exist! " + "Check your settings!" + .format(sysreg_parser_path_minidump)) + return + if os.path.getsize(os.path.join(out_dir, 'sysdbg_regs.bin')) > 0: + sysdbg_file = os.path.join(out_dir, 'sysdbg_regs.bin') + else: + return + p = subprocess.Popen([sys.executable, sysreg_parser_path_minidump, '-s', sysdbg_file, '--out-dir', out_dir], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + + print_out_str('--------') + print_out_str(p.communicate()[0]) + def sorted_dump_data_clients(self, ram_dump, table, table_num_entries): """ Returns a sorted list of (client_name, func, client_address) where @@ -768,6 +807,8 @@ class DebugImage_v2(): client_end, client_id, ram_dump) if ram_dump.dcc: self.parse_dcc(ram_dump) + if ram_dump.sysreg: + self.parse_sysreg(ram_dump) self.qdss.dump_standard(ram_dump) if not ram_dump.skip_qdss_bin: self.qdss.save_etf_bin(ram_dump) diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py index dd58a2088ee99abcce370cc4efd8d3d8574efefe..48778af43af2598658d667c4c3668d1851f90d4f 100644 --- a/linux-ramdump-parser-v2/ramdump.py +++ b/linux-ramdump-parser-v2/ramdump.py @@ -528,6 +528,7 @@ class RamDump(): self.qtf = options.qtf self.skip_qdss_bin = options.skip_qdss_bin self.dcc = False + self.sysreg = False self.t32_host_system = options.t32_host_system or None self.ipc_log_test = options.ipc_test self.ipc_log_skip = options.ipc_skip diff --git a/linux-ramdump-parser-v2/sysregs.py b/linux-ramdump-parser-v2/sysregs.py new file mode 100644 index 0000000000000000000000000000000000000000..fdcb4f36341319a4fb66ea47dfe83f74bf32776c --- /dev/null +++ b/linux-ramdump-parser-v2/sysregs.py @@ -0,0 +1,32 @@ +# Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 and +# only version 2 as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +import struct +import os +from print_out import print_out_str +from ramparse import VERSION + +class SysRegDump(): + + def __init__(self, start, end): + self.start_addr = start + self.end_addr = end + + def dump_sysreg_img(self,ram_dump): + if self.start_addr >= self.end_addr: + return False + rsz = self.end_addr - self.start_addr + sysregfile = ram_dump.open_file('sysdbg_regs.bin') + for i in range(0, rsz): + val = ram_dump.read_byte(self.start_addr + i, False) + sysregfile.write(struct.pack('<B', val)) + + sysregfile.close()