From 1722c90cfa54e8d61d808ca2fc5c4e73129c6ec7 Mon Sep 17 00:00:00 2001 From: Aparna Das <adas@codeaurora.org> Date: Fri, 28 Mar 2014 18:25:48 -0700 Subject: [PATCH] linux-ramdump-parser-v2: Add support for v2 memory dump Add support to the ramdump parser to parse debug image v2 format. Current support is for parsing cpu context and QDSS dumps. Change-Id: Ic7437e3b999845d607366bcf727f00078f81915a --- linux-ramdump-parser-v2/debug_image_v2.py | 237 +++++++++++++ .../parsers/debug_image.py | 23 +- linux-ramdump-parser-v2/qdss.py | 29 +- linux-ramdump-parser-v2/watchdog_v2.py | 331 ++++++++++++++++++ 4 files changed, 601 insertions(+), 19 deletions(-) create mode 100644 linux-ramdump-parser-v2/debug_image_v2.py create mode 100644 linux-ramdump-parser-v2/watchdog_v2.py diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py new file mode 100644 index 0000000..6851442 --- /dev/null +++ b/linux-ramdump-parser-v2/debug_image_v2.py @@ -0,0 +1,237 @@ +# Copyright (c) 2012-2014, 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 + +from print_out import print_out_str +from qdss import QDSSDump +from watchdog_v2 import TZRegDump_v2 + +MEMDUMPV2_MAGIC = 0x42445953 + +class client(object): + MSM_DUMP_DATA_CPU_CTX = 0x00 + MSM_DUMP_DATA_L1_INST_CACHE = 0x60 + MSM_DUMP_DATA_L1_DATA_CACHE = 0x80 + MSM_DUMP_DATA_ETM_REG = 0xA0 + MSM_DUMP_DATA_L2_CACHE = 0xC0 + MSM_DUMP_DATA_L3_CACHE = 0xD0 + MSM_DUMP_DATA_OCMEM = 0xE0 + MSM_DUMP_DATA_TMC_ETF = 0xF0 + MSM_DUMP_DATA_TMC_REG = 0x100 + MSM_DUMP_DATA_TMC_ETF_REG = 0x101 + MSM_DUMP_DATA_MAX = 0x110 + +client_table = { + 'MSM_DUMP_DATA_CPU_CTX': 'parse_cpu_ctx', + 'MSM_DUMP_DATA_L1_INST_CACHE': 'parse_l1_inst_cache', + 'MSM_DUMP_DATA_L1_DATA_CACHE': 'parse_l1_data_cache', + 'MSM_DUMP_DATA_ETM_REG': 'parse_qdss_common', + 'MSM_DUMP_DATA_L2_CACHE': 'parse_l2_cache', + 'MSM_DUMP_DATA_L3_CACHE': 'parse_l3_cache', + 'MSM_DUMP_DATA_OCMEM': 'parse_ocmem', + 'MSM_DUMP_DATA_TMC_ETF': 'parse_qdss_common', + 'MSM_DUMP_DATA_TMC_REG': 'parse_qdss_common', +} + +qdss_tag_to_field_name = { + 'MSM_DUMP_DATA_TMC_REG': 'tmc_etr_start', + 'MSM_DUMP_DATA_TMC_ETF': 'etf_start', + 'MSM_ETM0_REG': 'etm_regs0', + 'MSM_ETM1_REG': 'etm_regs1', + 'MSM_ETM2_REG': 'etm_regs2', + 'MSM_ETM3_REG': 'etm_regs3', +} + +class DebugImage_v2(): + + def __init__(self): + self.qdss = QDSSDump() + self.dump_type_lookup_table = [] + self.dump_table_id_lookup_table = [] + self.dump_data_id_lookup_table = [] + + def parse_cpu_ctx(self, start, end, client_id, ram_dump): + core = client_id - client.MSM_DUMP_DATA_CPU_CTX + + print_out_str( + 'Parsing CPU{2} context start {0:x} end {1:x}'.format(start, end, core)) + + regs = TZRegDump_v2() + if regs.init_regs(start, end, core, ram_dump) is False: + print_out_str('!!! Could not get registers from TZ dump') + return + regs.dump_core_pc(ram_dump) + regs.dump_all_regs(ram_dump) + + def parse_qdss_common(self, 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)) + + if client_id == client.MSM_DUMP_DATA_TMC_ETF_REG: + setattr(self.qdss, 'tmc_etf_start', start) + else: + setattr(self.qdss, qdss_tag_to_field_name[client_name], start) + + def parse_dump_v2(self, ram_dump): + self.dump_type_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( + 'msm_dump_type', 2) + self.dump_table_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( + 'msm_dump_table_ids', 0x110) + self.dump_data_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( + 'msm_dump_data_ids', 0x110) + cpu_present_bits = ram_dump.read_word('cpu_present_bits') + cpus = bin(cpu_present_bits).count('1') + # per cpu entries + for i in range(1, cpus): + + self.dump_data_id_lookup_table[ + client.MSM_DUMP_DATA_CPU_CTX + i] = 'MSM_DUMP_DATA_CPU_CTX' + self.dump_data_id_lookup_table[ + client.MSM_DUMP_DATA_L1_INST_CACHE + i] = 'MSM_DUMP_DATA_L1_INST_CACHE' + self.dump_data_id_lookup_table[ + client.MSM_DUMP_DATA_L1_DATA_CACHE + i] = 'MSM_DUMP_DATA_L1_DATA_CACHE' + self.dump_data_id_lookup_table[ + client.MSM_DUMP_DATA_ETM_REG + i] = 'MSM_DUMP_DATA_ETM_REG' + # 0x100 - tmc-etr registers and 0x101 - for tmc-etf registers + self.dump_data_id_lookup_table[ + client.MSM_DUMP_DATA_TMC_REG + 1] = 'MSM_DUMP_DATA_TMC_REG' + dump_table_ptr_offset = ram_dump.field_offset( + 'struct msm_memory_dump', 'table') + dump_table_version_offset = ram_dump.field_offset( + 'struct msm_dump_table', 'version') + dump_table_num_entry_offset = ram_dump.field_offset( + 'struct msm_dump_table', 'num_entries') + dump_table_entry_offset = ram_dump.field_offset( + 'struct msm_dump_table', 'entries') + dump_entry_id_offset = ram_dump.field_offset( + 'struct msm_dump_entry', 'id') + dump_entry_name_offset = ram_dump.field_offset( + 'struct msm_dump_entry', 'name') + dump_entry_type_offset = ram_dump.field_offset( + 'struct msm_dump_entry', 'type') + dump_entry_addr_offset = ram_dump.field_offset( + 'struct msm_dump_entry', 'addr') + dump_data_version_offset = ram_dump.field_offset( + 'struct msm_dump_data', 'version') + dump_data_magic_offset = ram_dump.field_offset( + 'struct msm_dump_data', 'magic') + dump_data_name_offset = ram_dump.field_offset( + 'struct msm_dump_data', 'name') + dump_data_addr_offset = ram_dump.field_offset( + 'struct msm_dump_data', 'addr') + dump_data_len_offset = ram_dump.field_offset( + 'struct msm_dump_data', 'len') + dump_data_reserved_offset = ram_dump.field_offset( + 'struct msm_dump_data', 'reserved') + dump_entry_size = ram_dump.sizeof('struct msm_dump_entry') + dump_data_size = ram_dump.sizeof('struct msm_dump_data') + + mem_dump_data = ram_dump.addr_lookup('memdump') + + mem_dump_table = ram_dump.read_word( + mem_dump_data + dump_table_ptr_offset) + + mem_table_version = ram_dump.read_u32( + mem_dump_table + dump_table_version_offset) + if mem_table_version is None: + print_out_str('Version is bogus! Can\'t parse debug image') + return + mem_table_num_entry = ram_dump.read_u32( + mem_dump_table + dump_table_num_entry_offset) + if mem_table_num_entry is None or mem_table_num_entry > 100: + print_out_str('num_entries is bogus! Can\'t parse debug image') + return + + print_out_str('\nDebug image version: {0}.{1} Number of table entries {2}'.format( + mem_table_version >> 20, mem_table_version & 0xFFFFF, mem_table_num_entry)) + print_out_str('--------') + + for i in range(0, mem_table_num_entry): + this_entry = mem_dump_table + dump_table_entry_offset + \ + i * dump_entry_size + entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset) + entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset) + entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset) + + if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table): + print_out_str( + '!!! Invalid dump table entry id found {0:x}'.format(entry_id)) + continue + + if entry_type > len(self.dump_type_lookup_table): + print_out_str( + '!!! Invalid dump table entry type found {0:x}'.format(entry_type)) + continue + + table_version = ram_dump.read_u32( + entry_addr + dump_table_version_offset, False) + if table_version is None: + print_out_str('Dump table entry version is bogus! Can\'t parse debug image') + return + table_num_entries = ram_dump.read_u32( + entry_addr + dump_table_num_entry_offset, False) + if table_num_entries is None or table_num_entries > 100: + print_out_str('Dump table entry num_entries is bogus! Can\'t parse debug image') + return + + print_out_str( + 'Debug image version: {0}.{1} Entry id: {2} Entry type: {3} Number of entries: {4}'.format( + table_version >> 20, table_version & 0xFFFFF, self.dump_table_id_lookup_table[entry_id], + self.dump_type_lookup_table[entry_type], table_num_entries)) + + for j in range(0, table_num_entries): + print_out_str('--------') + client_entry = entry_addr + dump_table_entry_offset + j * dump_entry_size + client_id = ram_dump.read_u32(client_entry + dump_entry_id_offset, False) + client_type = ram_dump.read_u32(client_entry + dump_entry_type_offset, False) + client_addr = ram_dump.read_word(client_entry + dump_entry_addr_offset, False) + + if client_id < 0 or client_id > len(self.dump_data_id_lookup_table): + print_out_str( + '!!! Invalid dump client id found {0:x}'.format(client_id)) + continue + + if client_type > len(self.dump_type_lookup_table): + print_out_str( + '!!! Invalid dump client type found {0:x}'.format(client_type)) + continue + + dump_data_magic = ram_dump.read_u32(client_addr + dump_data_magic_offset, False) + dump_data_version = ram_dump.read_u32(client_addr + dump_data_version_offset, False) + dump_data_addr = ram_dump.read_dword(client_addr + dump_data_addr_offset, False) + dump_data_len = ram_dump.read_dword(client_addr + dump_data_len_offset, False) + + client_name = self.dump_data_id_lookup_table[client_id] + if client_name not in client_table: + print_out_str( + '!!! {0} Does not have an associated function. The parser needs to be updated!'.format(client_name)) + else: + print_out_str('Parsing debug information for {0}. Version: {1} Magic: {2:x}'.format( + client_name, dump_data_version, dump_data_magic)) + + if dump_data_magic is None: + print_out_str( + "!!! Address {0:x} is bogus! Can't parse!".format(start)) + continue + + if dump_data_magic != MEMDUMPV2_MAGIC: + print_out_str( + "!!! Magic {0:x} doesn't match! No context will be parsed".format(dump_data_magic)) + continue + + func = client_table[client_name] + getattr(DebugImage_v2, func)(self, dump_data_addr, dump_data_addr + dump_data_len, + client_id, ram_dump) + + self.qdss.dump_all(ram_dump) diff --git a/linux-ramdump-parser-v2/parsers/debug_image.py b/linux-ramdump-parser-v2/parsers/debug_image.py index 3354c7f..d5f750a 100644 --- a/linux-ramdump-parser-v2/parsers/debug_image.py +++ b/linux-ramdump-parser-v2/parsers/debug_image.py @@ -16,6 +16,7 @@ from print_out import print_out_str from qdss import QDSSDump from cachedump import save_l1_dump, parse_cache_dump from watchdog import TZRegDump +from debug_image_v2 import DebugImage_v2 QDSS_MAGIC = 0x5D1DB1Bf @@ -126,12 +127,7 @@ class DebugImage(RamParser): setattr(self.qdss, tag_to_field_name[tag], start + 4096) - def parse(self): - if not self.ramdump.is_config_defined('CONFIG_MSM_MEMORY_DUMP'): - print_out_str( - '!!! Debug image was not enabled. No debug dump will be provided') - return - + def parse_dump(self): out_dir = self.ramdump.outdir self.name_lookup_table = self.ramdump.gdbmi.get_enum_lookup_table( 'dump_client_type', 32) @@ -195,3 +191,18 @@ class DebugImage(RamParser): print_out_str('--------') self.qdss.dump_all(self.ramdump) + + def parse(self): + # use the mem_dump_data variable to detect if debug image feature was compiled in, + # and memdump data variable for debug image v2 feature, rather than relying on + # configuration option. + if self.ramdump.addr_lookup('mem_dump_data'): + self.parse_dump() + elif self.ramdump.addr_lookup('memdump'): + regs = DebugImage_v2() + regs.parse_dump_v2(self.ramdump) + else: + print_out_str( + '!!! Debug image was not enabled. No debug dump will be provided') + return + diff --git a/linux-ramdump-parser-v2/qdss.py b/linux-ramdump-parser-v2/qdss.py index f8b3308..99825ae 100644 --- a/linux-ramdump-parser-v2/qdss.py +++ b/linux-ramdump-parser-v2/qdss.py @@ -216,7 +216,7 @@ class QDSSDump(): for a, b in tmc_registers.iteritems(): offset, name = b tmc_etf_out.write('{0} ({1}): {2:x}\n'.format( - a, name, ram_dump.read_word(self.tmc_etf_start + offset, False))) + a, name, ram_dump.read_u32(self.tmc_etf_start + offset, False))) tmc_etf_out.close() def print_tmc_etr(self, ram_dump): @@ -230,7 +230,7 @@ class QDSSDump(): for a, b in tmc_registers.iteritems(): offset, name = b tmc_etf_out.write('{0} ({1}): {2:x}\n'.format( - a, name, ram_dump.read_word(self.tmc_etr_start + offset, False))) + a, name, ram_dump.read_u32(self.tmc_etr_start + offset, False))) tmc_etf_out.close() def print_etm_registers(self, ram_dump, base, fname): @@ -238,7 +238,7 @@ class QDSSDump(): for a, b in etm_registers.iteritems(): offset, name = b etm_out.write('{0} ({1}): {2:x})\n'.format( - a, name, ram_dump.read_word(base + offset * 4, False))) + a, name, ram_dump.read_u32(base + offset * 4, False))) etm_out.close() def print_all_etm_register(self, ram_dump): @@ -275,13 +275,16 @@ class QDSSDump(): ctl_offset, ctl_desc = tmc_registers['CTL'] mode_offset, mode_desc = tmc_registers['MODE'] + rsz_offset, rsz_desc = tmc_registers['RSZ'] - ctl = ram_dump.read_word(self.tmc_etf_start + ctl_offset, False) - mode = ram_dump.read_word(self.tmc_etf_start + mode_offset, False) + ctl = ram_dump.read_u32(self.tmc_etf_start + ctl_offset, False) + mode = ram_dump.read_u32(self.tmc_etf_start + mode_offset, False) + rsz = ram_dump.read_u32(self.tmc_etf_start + rsz_offset, False) + # rsz is given in words so convert to bytes + rsz = 4 * rsz if (ctl & 0x1) == 1 and (mode == 0): - # Save the 64kb of data - for i in range(0, 64 * 1024): + for i in range(0, rsz): val = ram_dump.read_byte(self.etf_start + i, False) tmc_etf.write(struct.pack('<B', val)) else: @@ -299,24 +302,24 @@ class QDSSDump(): ctl_offset, ctl_desc = tmc_registers['CTL'] mode_offset, mode_desc = tmc_registers['MODE'] - ctl = ram_dump.read_word(self.tmc_etr_start + ctl_offset, False) - mode = ram_dump.read_word(self.tmc_etr_start + mode_offset, False) + ctl = ram_dump.read_u32(self.tmc_etr_start + ctl_offset, False) + mode = ram_dump.read_u32(self.tmc_etr_start + mode_offset, False) if (ctl & 0x1) == 1 and (mode == 0): sts_offset, sts_desc = tmc_registers['STS'] - sts = ram_dump.read_word(self.tmc_etr_start + sts_offset, False) + sts = ram_dump.read_u32(self.tmc_etr_start + sts_offset, False) dbalo_offset, dbalo_desc = tmc_registers['DBALO'] - dbalo = ram_dump.read_word( + dbalo = ram_dump.read_u32( self.tmc_etr_start + dbalo_offset, False) rsz_offset, rsz_desc = tmc_registers['RSZ'] - rsz = ram_dump.read_word(self.tmc_etr_start + rsz_offset, False) + rsz = ram_dump.read_u32(self.tmc_etr_start + rsz_offset, False) # rsz is given in words so convert to bytes rsz = 4 * rsz rwp_offset, rwp_desc = tmc_registers['RWP'] - rwp = ram_dump.read_word(self.tmc_etr_start + rwp_offset, False) + rwp = ram_dump.read_u32(self.tmc_etr_start + rwp_offset, False) if (sts & 0x1) == 1: for i in range(rwp, dbalo + rsz): diff --git a/linux-ramdump-parser-v2/watchdog_v2.py b/linux-ramdump-parser-v2/watchdog_v2.py new file mode 100644 index 0000000..1ef5e7d --- /dev/null +++ b/linux-ramdump-parser-v2/watchdog_v2.py @@ -0,0 +1,331 @@ +# Copyright (c) 2012-2014, 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 +from print_out import print_out_str + +# (name from tz dump, corresponding T32 register, whether or not to print_out_str (the function name)) +sysdbg_cpu64_register_names = [ + ('x0', 'x0', False), + ('x1', 'x1', False), + ('x2', 'x2', False), + ('x3', 'x3', False), + ('x4', 'x4', False), + ('x5', 'x5', False), + ('x6', 'x6', False), + ('x7', 'x7', False), + ('x8', 'x8', False), + ('x9', 'x9', False), + ('x10', 'x10', False), + ('x11', 'x11', False), + ('x12', 'x12', False), + ('x13', 'x13', False), + ('x14', 'x14', False), + ('x15', 'x15', False), + ('x16', 'x16', False), + ('x17', 'x17', False), + ('x18', 'x18', False), + ('x19', 'x19', False), + ('x20', 'x20', False), + ('x21', 'x21', False), + ('x22', 'x22', False), + ('x23', 'x23', False), + ('x24', 'x24', False), + ('x25', 'x25', False), + ('x26', 'x26', False), + ('x27', 'x27', False), + ('x28', 'x28', False), + ('x29', 'x29', False), + ('x30', 'x30', True), + ('pc', 'pc', True), + ('currentEL', None, False), + ('sp_el3', 'sp_el3', False), + ('elr_el3', 'elr_el3', True), + ('spsr_el3', 'spsr_el3', False), + ('sp_el2', 'sp_el2', False), + ('elr_el2', 'elr_el2', True), + ('spsr_el2', 'spsr_el2', False), + ('sp_el1', 'sp_el1', False), + ('elr_el1', 'elr_el1', True), + ('spsr_el1', 'spsr_el1', False), + ('sp_el0', 'sp_el0', False), + ('__reserved1', '__reserved1', False), + ('__reserved2', '__reserved2', False), + ('__reserved3', '__reserved3', False), + ('__reserved4', '__reserved4', False), +] + +sysdbg_cpu64_ctxt_regs_type = ''.join([ + 'Q', # x0 + 'Q', # x1 + 'Q', # x2 + 'Q', # x3 + 'Q', # x4 + 'Q', # x5 + 'Q', # x6 + 'Q', # x7 + 'Q', # x8 + 'Q', # x9 + 'Q', # x10 + 'Q', # x11 + 'Q', # x12 + 'Q', # x13 + 'Q', # x14 + 'Q', # x15 + 'Q', # x16 + 'Q', # x17 + 'Q', # x18 + 'Q', # x19 + 'Q', # x20 + 'Q', # x21 + 'Q', # x22 + 'Q', # x23 + 'Q', # x24 + 'Q', # x25 + 'Q', # x26 + 'Q', # x27 + 'Q', # x28 + 'Q', # x29 + 'Q', # x30 + 'Q', # pc + 'Q', # currentEL + 'Q', # sp_el3 + 'Q', # elr_el3 + 'Q', # spsr_el3 + 'Q', # sp_el2 + 'Q', # elr_el2 + 'Q', # spsr_el2 + 'Q', # sp_el1 + 'Q', # elr_el1 + 'Q', # spsr_el1 + 'Q', # sp_el0 + 'Q', # __reserved1 + 'Q', # __reserved2 + 'Q', # __reserved3 + 'Q', # __reserved4 +]) + +sysdbg_cpu32_register_names = [ + ('r0', 'r0', False), + ('r1', 'r1', False), + ('r2', 'r2', False), + ('r3', 'r3', False), + ('r4', 'r4', False), + ('r5', 'r5', False), + ('r6', 'r6', False), + ('r7', 'r7', False), + ('r8', 'r8', False), + ('r9', 'r9', False), + ('r10', 'r10', False), + ('r11', 'r11', False), + ('r12', 'r12', False), + ('r13_usr', 'r13_usr', False), + ('r14_usr', 'r14_usr', False), + ('r13_hyp', 'r13_hyp', False), + ('r14_irq', 'r14_irq', True), + ('r13_irq', 'r13_irq', False), + ('r14_svc', 'r14_svc', True), + ('r13_svc', 'r13_svc', False), + ('r14_abt', 'r14_abt', True), + ('r13_abt', 'r13_abt', False), + ('r14_und', 'r14_und', True), + ('r13_und', 'r13_und', False), + ('r8_fiq', 'r8_fiq', False), + ('r9_fiq', 'r9_fiq', False), + ('r10_fiq', 'r10_fiq', False), + ('r11_fiq', 'r11_fiq', False), + ('r12_fiq', 'r12_fiq', False), + ('r13_fiq', 'r13_fiq', False), + ('r14_fiq', 'r14_fiq', True), + ('pc', 'pc', True), + ('cpsr', 'cpsr', False), + ('r13_mon', 'r13_mon', False), + ('r14_mon', 'r14_mon', True), + ('r14_hyp', 'r14_hyp', True), + ('_reserved', '_reserved', False), + ('__reserved1', '__reserved1', False), + ('__reserved2', '__reserved2', False), + ('__reserved3', '__reserved3', False), + ('__reserved4', '__reserved4', False), +] + +sysdbg_cpu32_ctxt_regs_type = ''.join([ + 'Q', # r0 + 'Q', # r1 + 'Q', # r2 + 'Q', # r3 + 'Q', # r4 + 'Q', # r5 + 'Q', # r6 + 'Q', # r7 + 'Q', # r8 + 'Q', # r9 + 'Q', # r10 + 'Q', # r11 + 'Q', # r12 + 'Q', # r13_usr + 'Q', # r14_usr + 'Q', # r13_hyp + 'Q', # r14_irq + 'Q', # r13_irq + 'Q', # r14_svc + 'Q', # r13_svc + 'Q', # r14_abt + 'Q', # r13_abt + 'Q', # r14_und + 'Q', # r13_und + 'Q', # r8_fiq + 'Q', # r9_fiq + 'Q', # r10_fiq + 'Q', # r11_fiq + 'Q', # r12_fiq + 'Q', # r13_fiq + 'Q', # r14_fiq + 'Q', # pc + 'Q', # cpsr + 'Q', # r13_mon + 'Q', # r14_mon + 'Q', # r14_hyp + 'Q', # _reserved + 'Q', # __reserved1 + 'Q', # __reserved2 + 'Q', # __reserved3 + 'Q', # __reserved4 +]) + +cpu_name = ( + 'Invalid', + 'A53', + 'A57', + 'Hydra', +) + +class TZCpuCtx_v2(): + + def __init__(self, regs_t, ramdump): + i = 0 + self.regs = {} + for r in regs_t: + if ramdump.arm64: + self.regs[sysdbg_cpu64_register_names[i][0]] = r + else: + self.regs[sysdbg_cpu32_register_names[i][0]] = r + i += 1 + + def print_regs(self, outfile, ramdump): + if ramdump.arm64: + register_names = sysdbg_cpu64_register_names + else: + register_names = sysdbg_cpu32_register_names + for reg_name, t32_name, print_pc in register_names: + if print_pc: + a = ramdump.unwind_lookup(self.regs[reg_name]) + if a is not None: + symname, offset = ramdump.unwind_lookup( + self.regs[reg_name]) + pc_string = '[{0}+0x{1:x}]'.format(symname, offset) + else: + pc_string = None + else: + pc_string = None + if pc_string is not None: + print_out_str(' {0:8} = 0x{1:016x} {2}'.format( + reg_name, self.regs[reg_name], pc_string)) + else: + print_out_str(' {0:8} = 0x{1:016x}'.format( + reg_name, self.regs[reg_name])) + if t32_name is not None: + outfile.write( + 'r.s {0} 0x{1:x}\n'.format(t32_name, self.regs[reg_name])) + +class TZRegDump_v2(): + + def __init__(self): + self.core_regs = None + self.sec_regs = None + self.start_addr = 0 + self.end_addr = 0 + self.core = 0 + self.status = [] + + def dump_all_regs(self, ram_dump): + coren_regs = ram_dump.open_file('core{0}_regs.cmm'.format(self.core)) + + print_out_str('core{0} regs:'.format(self.core)) + self.core_regs.print_regs(coren_regs, ram_dump) + coren_regs.close() + + secure_regs = ram_dump.open_file('secure_world_core{0}_regs.cmm'.format(self.core)) + print_out_str('\n=============== secure contex ===========') + self.sec_regs.print_regs(secure_regs, ram_dump) + print_out_str('============ end secure context ===========') + secure_regs.close() + + def dump_core_pc(self, ram_dump): + print '' + pc = self.core_regs.regs['pc'] + if ram_dump.arm64: + lr = self.core_regs.regs['elr_el1'] + bt = self.core_regs.regs['sp_el1'] + else: + lr = self.core_regs.regs['r14_svc'] + bt = self.core_regs.regs['r13_svc'] + + a = ram_dump.unwind_lookup(pc) + if a is not None: + symname, offset = a + else: + symname = 'UNKNOWN' + offset = 0 + print_out_str( + 'Core {3} PC: {0}+{1:x} <{2:x}>'.format(symname, offset, pc, self.core)) + a = ram_dump.unwind_lookup(lr) + if a is not None: + symname, offset = a + else: + symname = 'UNKNOWN' + offset = 0 + print_out_str( + 'Core {3} LR: {0}+{1:x} <{2:x}>'.format(symname, offset, lr, self.core)) + print_out_str('') + ram_dump.unwind.unwind_backtrace(bt, 0, pc, lr, '') + print_out_str('') + + def init_regs(self, start_addr, end_addr, core, ram_dump): + self.start_addr = start_addr + self.end_addr = end_addr + self.core = core + + # uint32 status[4]; -- status fields + # sdi_cpu_ctxt_regs_type cpu_regs; -- ctxt for all cpus + # sdi_cpu_ctxt_regs_type __reserved3; -- secure ctxt + for i in range(0, 4): + self.status.append(ram_dump.read_u32(self.start_addr, False)) + self.start_addr += 4 + + if ram_dump.arm64: + sc_regs = ram_dump.read_string( + self.start_addr, sysdbg_cpu64_ctxt_regs_type, False) + self.start_addr += struct.calcsize(sysdbg_cpu64_ctxt_regs_type) + sc_secure = ram_dump.read_string( + self.start_addr, sysdbg_cpu64_ctxt_regs_type , False) + self.start_addr += struct.calcsize(sysdbg_cpu64_ctxt_regs_type) + else: + sc_regs = ram_dump.read_string( + self.start_addr, sysdbg_cpu32_ctxt_regs_type, False) + self.start_addr += struct.calcsize(sysdbg_cpu32_ctxt_regs_type) + sc_secure = ram_dump.read_string( + self.start_addr, sysdbg_cpu32_ctxt_regs_type , False) + self.start_addr += struct.calcsize(sysdbg_cpu32_ctxt_regs_type) + + self.core_regs = TZCpuCtx_v2(sc_regs, ram_dump) + self.sec_regs = TZCpuCtx_v2(sc_secure, ram_dump) + return True -- GitLab