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 ftrace_field_func(self, common_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_field', 'name') type_offset = ram_dump.field_offset('struct ftrace_event_field', 'type') filter_type_offset = ram_dump.field_offset('struct ftrace_event_field', 'filter_type') field_offset = ram_dump.field_offset('struct ftrace_event_field', 'offset') size_offset = ram_dump.field_offset('struct ftrace_event_field', 'size') signed_offset = ram_dump.field_offset('struct ftrace_event_field', 'is_signed') name = ram_dump.read_word(common_list + name_offset) field_name = ram_dump.read_cstring(name, 256) type_name = ram_dump.read_word(common_list + type_offset) type_str = ram_dump.read_cstring(type_name, 256) offset = ram_dump.read_u32(common_list + field_offset) size = ram_dump.read_u32(common_list + size_offset) signed = ram_dump.read_u32(common_list + signed_offset) if re.match('(.*)\[(.*)', type_str) and not(re.match('__data_loc', type_str)): s = re.split('\[', type_str) s[1] = '[' + s[1] self.formats_out.write("\tfield:{0} {1}{2};\toffset:{3};\tsize:{4};\tsigned:{5};\n".format(s[0], field_name, s[1], offset, size, signed)) else: self.formats_out.write("\tfield:{0} {1};\toffset:{2};\tsize:{3};\tsigned:{4};\n".format(type_str, field_name, offset, size, signed)) def ftrace_events_func(self, ftrace_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_call', 'name') event_offset = ram_dump.field_offset('struct ftrace_event_call', 'event') fmt_offset = ram_dump.field_offset('struct ftrace_event_call', 'print_fmt') class_offset = ram_dump.field_offset('struct ftrace_event_call', 'class') type_offset = ram_dump.field_offset('struct trace_event', 'type') fields_offset = ram_dump.field_offset('struct ftrace_event_class', 'fields') common_field_list = ram_dump.addr_lookup('ftrace_common_fields') field_next_offset = ram_dump.field_offset('struct ftrace_event_field', 'link') name = ram_dump.read_word(ftrace_list + name_offset) name_str = ram_dump.read_cstring(name, 512) event_id = ram_dump.read_word(ftrace_list + event_offset + type_offset) fmt = ram_dump.read_word(ftrace_list + fmt_offset) fmt_str = ram_dump.read_cstring(fmt, 2048) self.formats_out.write("name: {0}\n".format(name_str)) self.formats_out.write("ID: {0}\n".format(event_id)) self.formats_out.write("format:\n") list_walker = llist.ListWalker(ram_dump, common_field_list, field_next_offset) list_walker.walk_prev(common_field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") event_class = ram_dump.read_word(ftrace_list + class_offset) field_list = event_class + fields_offset list_walker = llist.ListWalker(ram_dump, field_list, field_next_offset) list_walker.walk_prev(field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") self.formats_out.write("print fmt: {0}\n".format(fmt_str)) def collect_ftrace_format(self, ram_dump): formats = os.path.join('qtf', 'map_files', 'formats.txt') formats_out = ram_dump.open_file(formats) self.formats_out = formats_out ftrace_events_list = ram_dump.addr_lookup('ftrace_events') next_offset = ram_dump.field_offset('struct ftrace_event_call', 'list') list_walker = llist.ListWalker(ram_dump, ftrace_events_list, next_offset) list_walker.walk_prev(ftrace_events_list, self.ftrace_events_func, ram_dump) self.formats_out.close def parse_qtf(self, ram_dump): out_dir = ram_dump.outdir if platform.system() != 'Windows': return qtf_path = ram_dump.qtf_path if qtf_path is None: try: import local_settings try: qtf_path = local_settings.qtf_path except AttributeError as e: print_out_str("attribute qtf_path in local_settings.py looks bogus. Please see README.txt") print_out_str("Full message: %s" % e.message) return except ImportError: print_out_str("missing qtf_path local_settings.") print_out_str("Please see the README for instructions on setting up local_settings.py") return if qtf_path is None: print_out_str("!!! Incorrect path for qtf specified.") print_out_str("!!! Please see the README for instructions on setting up local_settings.py") return if not os.path.exists(qtf_path): print_out_str("!!! qtf_path {0} does not exist! Check your settings!".format(qtf_path)) return if not os.access(qtf_path, os.X_OK): print_out_str("!!! No execute permissions on qtf path {0}".format(qtf_path)) return if os.path.getsize(os.path.join(out_dir, 'tmc-etf.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etf.bin') elif os.path.getsize(os.path.join(out_dir, 'tmc-etr.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etr.bin') else: return port = 12345 qtf_dir = os.path.join(out_dir, 'qtf') workspace = os.path.join(qtf_dir, 'qtf.workspace') qtf_out = os.path.join(out_dir, 'qtf.txt') chipset = 'msm' + str(ram_dump.hw_id) hlos = 'LA' p = subprocess.Popen([qtf_path, '-s', '{0}'.format(port)]) subprocess.call('{0} -c {1} new workspace {2} {3} {4}'.format(qtf_path, port, qtf_dir, chipset, hlos)) self.collect_ftrace_format(ram_dump) subprocess.call('{0} -c {1} open workspace {2}'.format(qtf_path, port, workspace)) subprocess.call('{0} -c {1} open bin {2}'.format(qtf_path, port, trace_file)) subprocess.call('{0} -c {1} stream trace table {2}'.format(qtf_path, port, qtf_out)) subprocess.call('{0} -c {1} exit'.format(qtf_path, port)) p.communicate('quit') 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', 0x112) 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' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_LOG_BUF] = 'MSM_DUMP_DATA_LOG_BUF' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_LOG_BUF_FIRST_IDX] = 'MSM_DUMP_DATA_LOG_BUF_FIRST_IDX' 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) if ram_dump.qtf: self.parse_qtf(ram_dump)
class DebugImage(RamParser): def __init__(self, *args): super(DebugImage, self).__init__(*args) self.qdss = QDSSDump() self.name_lookup_table = [] def parse_cpu_ctx(self, start, end, tag): print_out_str('Parsing CPU context start {0:x} end {1:x}'.format( start, end)) # For historical reasons, we can't rely on the magic number to indicate if there # is context dumped. Check the magic number here instead magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != 0x44434151: print_out_str( "!!! Magic {0:x} doesn't match! No context was dumped!".format( magic)) return regs = TZRegDump(self.ramdump) regs.init_regs(start) for i in range(regs.ncores): regs.dump_core_pc(i) regs.dump_all_regs() def parse_l2_cache(self, start, end, tag): print_out_str('Parsing L2 cache context start {0:x} end {1:x}'.format( start, end)) magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != 0xcac1ecac: print_out_str( "!!! Magic {0:x} doesn't match! No cache was dumped!".format( magic)) return parse_cache_dump(self.ramdump, start) def parse_l1_cache(self, start, end, tag): print_out_str('Parsing L1 cache context start {0:x} end {1:x}'.format( start, end)) magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != 0x314C4151: print_out_str( "!!! Magic {0:X} doesn't match! No cache was dumped!".format( magic)) return print_out_str('Saving L1 cache') save_l1_dump(self.ramdump, start, end - start) def parse_ocmem(self, start, end, tag): print_out_str( '[!!!] Parsing not implemented yet start {0:x} end {1:x}'.format( start, end)) def parse_qdss_common(self, start, end, tag): print_out_str('Parsing {0} context start {1:x} end {2:x}'.format( tag, start, end)) magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != QDSS_MAGIC: print_out_str( "!!! Magic {0:X} doesn't match! Tracing was not dumped!". format(magic)) return setattr(self.qdss, tag_to_field_name[tag], start + 4096) def parse_dump(self): out_dir = self.ramdump.outdir self.name_lookup_table = self.ramdump.gdbmi.get_enum_lookup_table( 'dump_client_type', 32) dump_table_ptr_offset = self.ramdump.field_offset( 'struct msm_memory_dump', 'dump_table_ptr') version_offset = self.ramdump.field_offset('struct msm_dump_table', 'version') num_entries_offset = self.ramdump.field_offset('struct msm_dump_table', 'num_entries') client_entries_offset = self.ramdump.field_offset( 'struct msm_dump_table', 'client_entries') id_offset = self.ramdump.field_offset('struct msm_client_dump', 'id') start_addr_offset = self.ramdump.field_offset('struct msm_client_dump', 'start_addr') end_addr_offset = self.ramdump.field_offset('struct msm_client_dump', 'end_addr') client_dump_entry_size = self.ramdump.sizeof('struct msm_client_dump') mem_dump_data = self.ramdump.addr_lookup('mem_dump_data') dump_table = self.ramdump.read_word(mem_dump_data + dump_table_ptr_offset) version = self.ramdump.read_word(dump_table + version_offset) if version is None: print_out_str('Version is bogus! Can\'t parse debug image') return num_entries = self.ramdump.read_word(dump_table + num_entries_offset) if num_entries is None or num_entries > 100: print_out_str('num_entries is bogus! Can\'t parse debug image') return print_out_str( '\nDebug image version: {0}.{1} Number of entries {2}'.format( version >> 20, version & 0xFFFFF, num_entries)) print_out_str('--------') for i in range(0, num_entries): this_client = dump_table + client_entries_offset + \ i * client_dump_entry_size client_id = self.ramdump.read_word(this_client + id_offset) client_start = self.ramdump.read_word(this_client + start_addr_offset) client_end = self.ramdump.read_word(this_client + end_addr_offset) if client_id < 0 or client_id > len(self.name_lookup_table): print_out_str( '!!! Invalid client id found {0:x}'.format(client_id)) continue client_name = self.name_lookup_table[client_id] if client_name not in print_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}'.format(client_name)) func = print_table[client_name] getattr(DebugImage, func)(self, client_start, client_end, client_name) 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
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, version, start, end, client_id, ram_dump): core = client_id - client.MSM_DUMP_DATA_CPU_CTX if ram_dump.Is_Dakota(): core = 0 print_out_str('Parsing CPU{2} context start {0:x} end {1:x}'.format( start, end, core)) regs = TZRegDump_v2() if regs.init_regs(version, 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 ftrace_field_func(self, common_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_field', 'name') type_offset = ram_dump.field_offset('struct ftrace_event_field', 'type') filter_type_offset = ram_dump.field_offset('struct ftrace_event_field', 'filter_type') field_offset = ram_dump.field_offset('struct ftrace_event_field', 'offset') size_offset = ram_dump.field_offset('struct ftrace_event_field', 'size') signed_offset = ram_dump.field_offset('struct ftrace_event_field', 'is_signed') name = ram_dump.read_word(common_list + name_offset) field_name = ram_dump.read_cstring(name, 256) type_name = ram_dump.read_word(common_list + type_offset) type_str = ram_dump.read_cstring(type_name, 256) offset = ram_dump.read_u32(common_list + field_offset) size = ram_dump.read_u32(common_list + size_offset) signed = ram_dump.read_u32(common_list + signed_offset) if re.match('(.*)\[(.*)', type_str) and not (re.match('__data_loc', type_str)): s = re.split('\[', type_str) s[1] = '[' + s[1] self.formats_out.write( "\tfield:{0} {1}{2};\toffset:{3};\tsize:{4};\tsigned:{5};\n". format(s[0], field_name, s[1], offset, size, signed)) else: self.formats_out.write( "\tfield:{0} {1};\toffset:{2};\tsize:{3};\tsigned:{4};\n". format(type_str, field_name, offset, size, signed)) def ftrace_events_func(self, ftrace_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_call', 'name') event_offset = ram_dump.field_offset('struct ftrace_event_call', 'event') fmt_offset = ram_dump.field_offset('struct ftrace_event_call', 'print_fmt') class_offset = ram_dump.field_offset('struct ftrace_event_call', 'class') type_offset = ram_dump.field_offset('struct trace_event', 'type') fields_offset = ram_dump.field_offset('struct ftrace_event_class', 'fields') common_field_list = ram_dump.addr_lookup('ftrace_common_fields') field_next_offset = ram_dump.field_offset('struct ftrace_event_field', 'link') name = ram_dump.read_word(ftrace_list + name_offset) name_str = ram_dump.read_cstring(name, 512) event_id = ram_dump.read_word(ftrace_list + event_offset + type_offset) fmt = ram_dump.read_word(ftrace_list + fmt_offset) fmt_str = ram_dump.read_cstring(fmt, 2048) self.formats_out.write("name: {0}\n".format(name_str)) self.formats_out.write("ID: {0}\n".format(event_id)) self.formats_out.write("format:\n") list_walker = llist.ListWalker(ram_dump, common_field_list, field_next_offset) list_walker.walk_prev(common_field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") event_class = ram_dump.read_word(ftrace_list + class_offset) field_list = event_class + fields_offset list_walker = llist.ListWalker(ram_dump, field_list, field_next_offset) list_walker.walk_prev(field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") self.formats_out.write("print fmt: {0}\n".format(fmt_str)) def collect_ftrace_format(self, ram_dump): formats = os.path.join('qtf', 'map_files', 'formats.txt') formats_out = ram_dump.open_file(formats) self.formats_out = formats_out ftrace_events_list = ram_dump.addr_lookup('ftrace_events') next_offset = ram_dump.field_offset('struct ftrace_event_call', 'list') list_walker = llist.ListWalker(ram_dump, ftrace_events_list, next_offset) list_walker.walk_prev(ftrace_events_list, self.ftrace_events_func, ram_dump) self.formats_out.close def parse_qtf(self, ram_dump): out_dir = ram_dump.outdir if platform.system() != 'Windows': return qtf_path = ram_dump.qtf_path if qtf_path is None: try: import local_settings try: qtf_path = local_settings.qtf_path except AttributeError as e: print_out_str( "attribute qtf_path in local_settings.py looks bogus. Please see README.txt" ) print_out_str("Full message: %s" % e.message) return except ImportError: print_out_str("missing qtf_path local_settings.") print_out_str( "Please see the README for instructions on setting up local_settings.py" ) return if qtf_path is None: print_out_str("!!! Incorrect path for qtf specified.") print_out_str( "!!! Please see the README for instructions on setting up local_settings.py" ) return if not os.path.exists(qtf_path): print_out_str( "!!! qtf_path {0} does not exist! Check your settings!".format( qtf_path)) return if not os.access(qtf_path, os.X_OK): print_out_str( "!!! No execute permissions on qtf path {0}".format(qtf_path)) return if os.path.getsize(os.path.join(out_dir, 'tmc-etf.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etf.bin') elif os.path.getsize(os.path.join(out_dir, 'tmc-etr.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etr.bin') else: return port = 12345 qtf_dir = os.path.join(out_dir, 'qtf') workspace = os.path.join(qtf_dir, 'qtf.workspace') qtf_out = os.path.join(out_dir, 'qtf.txt') chipset = 'msm' + str(ram_dump.hw_id) hlos = 'LA' p = subprocess.Popen([qtf_path, '-s', '{0}'.format(port)]) subprocess.call('{0} -c {1} new workspace {2} {3} {4}'.format( qtf_path, port, qtf_dir, chipset, hlos)) self.collect_ftrace_format(ram_dump) subprocess.call('{0} -c {1} open workspace {2}'.format( qtf_path, port, workspace)) subprocess.call('{0} -c {1} open bin {2}'.format( qtf_path, port, trace_file)) subprocess.call('{0} -c {1} stream trace table {2}'.format( qtf_path, port, qtf_out)) subprocess.call('{0} -c {1} exit'.format(qtf_path, port)) p.communicate('quit') 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', 0x112) 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' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_LOG_BUF] = 'MSM_DUMP_DATA_LOG_BUF' self.dump_data_id_lookup_table[ client. MSM_DUMP_DATA_LOG_BUF_FIRST_IDX] = 'MSM_DUMP_DATA_LOG_BUF_FIRST_IDX' 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) if ram_dump.qtf: self.parse_qtf(ram_dump)
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, version, 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(version, 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_pmic(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)) regs = PmicRegDump(start, end) if regs.parse_all_regs(ram_dump) is False: print_out_str('!!! Could not get registers from PMIC dump') return regs.dump_all_regs(ram_dump) def parse_dcc_reg(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)) regs = DccRegDump(start, end) if regs.parse_all_regs(ram_dump) is False: print_out_str('!!! Could not get registers from DCC register dump') return regs.dump_all_regs(ram_dump) return def parse_dcc_sram(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)) regs = DccSramDump(start, end) if regs.dump_sram_img(ram_dump) is False: print_out_str('!!! Could not dump SRAM') else: ram_dump.dcc = True return def parse_vsens(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)) regs = VsensData() if regs.init_dump_regs(start, end, ram_dump) is False: print_out_str('!!! Could not get registers from Vsens Dump') return regs.print_vsens_regs(ram_dump) def parse_qdss_common(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)) 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_cache_common(self, version, start, end, client_id, ramdump): client_name = self.dump_data_id_lookup_table[client_id] core = client_id & 0xF filename = '{0}_0x{1:x}'.format(client_name, core) outfile = ramdump.open_file(filename) cache_type = lookup_cache_type(ramdump.hw_id, client_id, version) try: cache_type.parse(start, end, ramdump, outfile) except NotImplementedError: print_out_str('Cache dumping not supported for %s on this target' % client_name) except: print_out_str('!!! Unhandled exception while running {0}'.format( client_name)) print_out_exception() outfile.close() def ftrace_field_func(self, common_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_field', 'name') type_offset = ram_dump.field_offset('struct ftrace_event_field', 'type') filter_type_offset = ram_dump.field_offset('struct ftrace_event_field', 'filter_type') field_offset = ram_dump.field_offset('struct ftrace_event_field', 'offset') size_offset = ram_dump.field_offset('struct ftrace_event_field', 'size') signed_offset = ram_dump.field_offset('struct ftrace_event_field', 'is_signed') name = ram_dump.read_word(common_list + name_offset) field_name = ram_dump.read_cstring(name, 256) type_name = ram_dump.read_word(common_list + type_offset) type_str = ram_dump.read_cstring(type_name, 256) offset = ram_dump.read_u32(common_list + field_offset) size = ram_dump.read_u32(common_list + size_offset) signed = ram_dump.read_u32(common_list + signed_offset) if re.match('(.*)\[(.*)', type_str) and not (re.match('__data_loc', type_str)): s = re.split('\[', type_str) s[1] = '[' + s[1] self.formats_out.write( "\tfield:{0} {1}{2};\toffset:{3};\tsize:{4};\tsigned:{5};\n". format(s[0], field_name, s[1], offset, size, signed)) else: self.formats_out.write( "\tfield:{0} {1};\toffset:{2};\tsize:{3};\tsigned:{4};\n". format(type_str, field_name, offset, size, signed)) def ftrace_events_func(self, ftrace_list, ram_dump): event_offset = ram_dump.field_offset('struct ftrace_event_call', 'event') fmt_offset = ram_dump.field_offset('struct ftrace_event_call', 'print_fmt') class_offset = ram_dump.field_offset('struct ftrace_event_call', 'class') flags_offset = ram_dump.field_offset('struct ftrace_event_call', 'flags') flags = ram_dump.read_word(ftrace_list + flags_offset) if (ram_dump.kernel_version >= (3, 18) and (flags & TRACE_EVENT_FL_TRACEPOINT)): tp_offset = ram_dump.field_offset('struct ftrace_event_call', 'tp') tp_name_offset = ram_dump.field_offset('struct tracepoint', 'name') tp = ram_dump.read_word(ftrace_list + tp_offset) name = ram_dump.read_word(tp + tp_name_offset) else: name_offset = ram_dump.field_offset('struct ftrace_event_call', 'name') name = ram_dump.read_word(ftrace_list + name_offset) type_offset = ram_dump.field_offset('struct trace_event', 'type') fields_offset = ram_dump.field_offset('struct ftrace_event_class', 'fields') common_field_list = ram_dump.address_of('ftrace_common_fields') field_next_offset = ram_dump.field_offset('struct ftrace_event_field', 'link') name_str = ram_dump.read_cstring(name, 512) event_id = ram_dump.read_word(ftrace_list + event_offset + type_offset) fmt = ram_dump.read_word(ftrace_list + fmt_offset) fmt_str = ram_dump.read_cstring(fmt, 2048) self.formats_out.write("name: {0}\n".format(name_str)) self.formats_out.write("ID: {0}\n".format(event_id)) self.formats_out.write("format:\n") list_walker = llist.ListWalker(ram_dump, common_field_list, field_next_offset) list_walker.walk_prev(common_field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") event_class = ram_dump.read_word(ftrace_list + class_offset) field_list = event_class + fields_offset list_walker = llist.ListWalker(ram_dump, field_list, field_next_offset) list_walker.walk_prev(field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") self.formats_out.write("print fmt: {0}\n".format(fmt_str)) def collect_ftrace_format(self, ram_dump): formats = os.path.join('qtf', 'map_files', 'formats.txt') formats_out = ram_dump.open_file(formats) self.formats_out = formats_out ftrace_events_list = ram_dump.address_of('ftrace_events') next_offset = ram_dump.field_offset('struct ftrace_event_call', 'list') list_walker = llist.ListWalker(ram_dump, ftrace_events_list, next_offset) list_walker.walk_prev(ftrace_events_list, self.ftrace_events_func, ram_dump) self.formats_out.close def parse_qtf(self, ram_dump): out_dir = ram_dump.outdir if platform.system() != 'Windows': return qtf_path = ram_dump.qtf_path if qtf_path is None: try: import local_settings try: qtf_path = local_settings.qtf_path except AttributeError as e: print_out_str( "attribute qtf_path in local_settings.py looks bogus. Please see README.txt" ) print_out_str("Full message: %s" % e.message) return except ImportError: print_out_str("missing qtf_path local_settings.") print_out_str( "Please see the README for instructions on setting up local_settings.py" ) return if qtf_path is None: print_out_str("!!! Incorrect path for qtf specified.") print_out_str( "!!! Please see the README for instructions on setting up local_settings.py" ) return if not os.path.exists(qtf_path): print_out_str( "!!! qtf_path {0} does not exist! Check your settings!".format( qtf_path)) return if not os.access(qtf_path, os.X_OK): print_out_str( "!!! No execute permissions on qtf path {0}".format(qtf_path)) return if os.path.getsize(os.path.join(out_dir, 'tmc-etf.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etf.bin') elif os.path.getsize(os.path.join(out_dir, 'tmc-etr.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etr.bin') else: return port = None server_proc = None qtf_success = False max_tries = 3 qtf_dir = os.path.join(out_dir, 'qtf') workspace = os.path.join(qtf_dir, 'qtf.workspace') qtf_out = os.path.join(out_dir, 'qtf.txt') chipset = 'msm' + str(ram_dump.hw_id) hlos = 'LA' # Resolve any port collisions with other running qtf_server instances for tries in range(max_tries): port = random.randint(12000, 13000) server_proc = subprocess.Popen( [qtf_path, '-s', '{0}'.format(port)], stderr=subprocess.PIPE) time.sleep(1) server_proc.poll() if server_proc.returncode == 1: server_proc.terminate() continue else: qtf_success = True break if not qtf_success: server_proc.terminate() print_out_str('!!! Could not open a QTF server instance with a ' 'unique port (last port tried: ' '{0})'.format(str(port))) print_out_str('!!! Please kill all currently running qtf_server ' 'processes and try again') return subprocess.call('{0} -c {1} new workspace {2} {3} {4}'.format( qtf_path, port, qtf_dir, chipset, hlos)) self.collect_ftrace_format(ram_dump) subprocess.call('{0} -c {1} open workspace {2}'.format( qtf_path, port, workspace)) subprocess.call('{0} -c {1} open bin {2}'.format( qtf_path, port, trace_file)) subprocess.call('{0} -c {1} stream trace table {2}'.format( qtf_path, port, qtf_out)) subprocess.call('{0} -c {1} close'.format(qtf_path, port)) subprocess.call('{0} -c {1} exit'.format(qtf_path, port)) server_proc.communicate('quit') def parse_dcc(self, ram_dump): out_dir = ram_dump.outdir dcc_parser_path = os.path.join(os.path.dirname(__file__), '..', 'dcc_parser', 'dcc_parser.py') if dcc_parser_path is None: print_out_str("!!! Incorrect path for DCC specified.") return if not os.path.exists(dcc_parser_path): print_out_str( "!!! dcc_parser_path {0} does not exist! Check your settings!". format(dcc_parser_path)) return if os.path.getsize(os.path.join(out_dir, 'sram.bin')) > 0: sram_file = os.path.join(out_dir, 'sram.bin') else: return p = subprocess.Popen([ sys.executable, dcc_parser_path, '-s', sram_file, '--out-dir', out_dir ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print_out_str('--------') print_out_str(p.communicate()[0]) 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', MAX_NUM_ENTRIES) self.dump_data_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( 'msm_dump_data_ids', MAX_NUM_ENTRIES) 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_TLB + i] = 'MSM_DUMP_DATA_L1_INST_TLB' self.dump_data_id_lookup_table[client.MSM_DUMP_DATA_L1_DATA_TLB + i] = 'MSM_DUMP_DATA_L1_DATA_TLB' 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_L2_CACHE + i] = 'MSM_DUMP_DATA_L2_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' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_LOG_BUF] = 'MSM_DUMP_DATA_LOG_BUF' self.dump_data_id_lookup_table[ client. MSM_DUMP_DATA_LOG_BUF_FIRST_IDX] = 'MSM_DUMP_DATA_LOG_BUF_FIRST_IDX' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_L2_TLB] = 'MSM_DUMP_DATA_L2_TLB' 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.address_of('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_name = ram_dump.read_cstring( client_addr + dump_data_name_offset, ram_dump.sizeof('((struct msm_dump_data *)0x0)->name'), 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} Source: {3}' .format(client_name, dump_data_version, dump_data_magic, dump_data_name)) 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_version, dump_data_addr, dump_data_addr + dump_data_len, client_id, ram_dump) self.qdss.dump_all(ram_dump) if ram_dump.qtf: self.parse_qtf(ram_dump) if ram_dump.dcc: self.parse_dcc(ram_dump)
class DebugImage(RamParser): def __init__(self, *args): super(DebugImage, self).__init__(*args) self.qdss = QDSSDump() self.name_lookup_table = [] def parse_cpu_ctx(self, start, end, tag): print_out_str( 'Parsing CPU context start {0:x} end {1:x}'.format(start, end)) # For historical reasons, we can't rely on the magic number to indicate if there # is context dumped. Check the magic number here instead magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != 0x44434151: print_out_str( "!!! Magic {0:x} doesn't match! No context was dumped!".format(magic)) return regs = TZRegDump(self.ramdump) regs.init_regs(start) for i in range(regs.ncores): regs.dump_core_pc(i) regs.dump_all_regs() def parse_l2_cache(self, start, end, tag): print_out_str( 'Parsing L2 cache context start {0:x} end {1:x}'.format(start, end)) magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != 0xcac1ecac: print_out_str( "!!! Magic {0:x} doesn't match! No cache was dumped!".format(magic)) return parse_cache_dump(self.ramdump, start) def parse_l1_cache(self, start, end, tag): print_out_str( 'Parsing L1 cache context start {0:x} end {1:x}'.format(start, end)) magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != 0x314C4151: print_out_str( "!!! Magic {0:X} doesn't match! No cache was dumped!".format(magic)) return print_out_str('Saving L1 cache') save_l1_dump(self.ramdump, start, end - start) def parse_ocmem(self, start, end, tag): print_out_str( '[!!!] Parsing not implemented yet start {0:x} end {1:x}'.format(start, end)) def parse_qdss_common(self, start, end, tag): print_out_str( 'Parsing {0} context start {1:x} end {2:x}'.format(tag, start, end)) magic = self.ramdump.read_word(start, False) if magic is None: print_out_str( "!!! Address {0:x} is bogus! Can't parse!".format(start)) return if magic != QDSS_MAGIC: print_out_str( "!!! Magic {0:X} doesn't match! Tracing was not dumped!".format(magic)) return setattr(self.qdss, tag_to_field_name[tag], start + 4096) def parse_dump(self): out_dir = self.ramdump.outdir self.name_lookup_table = self.ramdump.gdbmi.get_enum_lookup_table( 'dump_client_type', 32) dump_table_ptr_offset = self.ramdump.field_offset( 'struct msm_memory_dump', 'dump_table_ptr') version_offset = self.ramdump.field_offset( 'struct msm_dump_table', 'version') num_entries_offset = self.ramdump.field_offset( 'struct msm_dump_table', 'num_entries') client_entries_offset = self.ramdump.field_offset( 'struct msm_dump_table', 'client_entries') id_offset = self.ramdump.field_offset('struct msm_client_dump', 'id') start_addr_offset = self.ramdump.field_offset( 'struct msm_client_dump', 'start_addr') end_addr_offset = self.ramdump.field_offset( 'struct msm_client_dump', 'end_addr') client_dump_entry_size = self.ramdump.sizeof('struct msm_client_dump') mem_dump_data = self.ramdump.address_of('mem_dump_data') dump_table = self.ramdump.read_word( mem_dump_data + dump_table_ptr_offset) version = self.ramdump.read_word(dump_table + version_offset) if version is None: print_out_str('Version is bogus! Can\'t parse debug image') return num_entries = self.ramdump.read_word(dump_table + num_entries_offset) if num_entries is None or num_entries > 100: print_out_str('num_entries is bogus! Can\'t parse debug image') return print_out_str('\nDebug image version: {0}.{1} Number of entries {2}'.format( version >> 20, version & 0xFFFFF, num_entries)) print_out_str('--------') for i in range(0, num_entries): this_client = dump_table + client_entries_offset + \ i * client_dump_entry_size client_id = self.ramdump.read_word(this_client + id_offset) client_start = self.ramdump.read_word( this_client + start_addr_offset) client_end = self.ramdump.read_word(this_client + end_addr_offset) if client_id < 0 or client_id > len(self.name_lookup_table): print_out_str( '!!! Invalid client id found {0:x}'.format(client_id)) continue client_name = self.name_lookup_table[client_id] if client_name not in print_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}'.format(client_name)) func = print_table[client_name] getattr(DebugImage, func)(self, client_start, client_end, client_name) 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.address_of('mem_dump_data'): self.parse_dump() elif self.ramdump.address_of('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
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, version, 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(version, 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_pmic(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)) regs = PmicRegDump(start, end) if regs.parse_all_regs(ram_dump) is False: print_out_str('!!! Could not get registers from PMIC dump') return regs.dump_all_regs(ram_dump) def parse_dcc_reg(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)) regs = DccRegDump(start, end) if regs.parse_all_regs(ram_dump) is False: print_out_str('!!! Could not get registers from DCC register dump') return regs.dump_all_regs(ram_dump) return def parse_dcc_sram(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)) regs = DccSramDump(start, end) if regs.dump_sram_img(ram_dump) is False: print_out_str('!!! Could not dump SRAM') else: ram_dump.dcc = True return def parse_vsens(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)) regs = VsensData() if regs.init_dump_regs(start, end, ram_dump) is False: print_out_str('!!! Could not get registers from Vsens Dump') return regs.print_vsens_regs(ram_dump) def parse_qdss_common(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)) 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_cache_common(self, version, start, end, client_id, ramdump): client_name = self.dump_data_id_lookup_table[client_id] core = client_id & 0xF filename = '{0}_0x{1:x}'.format(client_name, core) outfile = ramdump.open_file(filename) cache_type = lookup_cache_type(ramdump.hw_id, client_id, version) try: cache_type.parse(start, end, ramdump, outfile) except NotImplementedError: print_out_str('Cache dumping not supported for %s on this target' % client_name) except: print_out_str('!!! Unhandled exception while running {0}'.format(client_name)) print_out_exception() outfile.close() def ftrace_field_func(self, common_list, ram_dump): name_offset = ram_dump.field_offset('struct ftrace_event_field', 'name') type_offset = ram_dump.field_offset('struct ftrace_event_field', 'type') filter_type_offset = ram_dump.field_offset('struct ftrace_event_field', 'filter_type') field_offset = ram_dump.field_offset('struct ftrace_event_field', 'offset') size_offset = ram_dump.field_offset('struct ftrace_event_field', 'size') signed_offset = ram_dump.field_offset('struct ftrace_event_field', 'is_signed') name = ram_dump.read_word(common_list + name_offset) field_name = ram_dump.read_cstring(name, 256) type_name = ram_dump.read_word(common_list + type_offset) type_str = ram_dump.read_cstring(type_name, 256) offset = ram_dump.read_u32(common_list + field_offset) size = ram_dump.read_u32(common_list + size_offset) signed = ram_dump.read_u32(common_list + signed_offset) if re.match('(.*)\[(.*)', type_str) and not(re.match('__data_loc', type_str)): s = re.split('\[', type_str) s[1] = '[' + s[1] self.formats_out.write("\tfield:{0} {1}{2};\toffset:{3};\tsize:{4};\tsigned:{5};\n".format(s[0], field_name, s[1], offset, size, signed)) else: self.formats_out.write("\tfield:{0} {1};\toffset:{2};\tsize:{3};\tsigned:{4};\n".format(type_str, field_name, offset, size, signed)) def ftrace_events_func(self, ftrace_list, ram_dump): event_offset = ram_dump.field_offset('struct ftrace_event_call', 'event') fmt_offset = ram_dump.field_offset('struct ftrace_event_call', 'print_fmt') class_offset = ram_dump.field_offset('struct ftrace_event_call', 'class') flags_offset = ram_dump.field_offset('struct ftrace_event_call', 'flags') flags = ram_dump.read_word(ftrace_list + flags_offset) if (ram_dump.kernel_version >= (3, 18) and (flags & TRACE_EVENT_FL_TRACEPOINT)): tp_offset = ram_dump.field_offset('struct ftrace_event_call', 'tp') tp_name_offset = ram_dump.field_offset('struct tracepoint', 'name') tp = ram_dump.read_word(ftrace_list + tp_offset) name = ram_dump.read_word(tp + tp_name_offset) else: name_offset = ram_dump.field_offset('struct ftrace_event_call', 'name') name = ram_dump.read_word(ftrace_list + name_offset) type_offset = ram_dump.field_offset('struct trace_event', 'type') fields_offset = ram_dump.field_offset('struct ftrace_event_class', 'fields') common_field_list = ram_dump.address_of('ftrace_common_fields') field_next_offset = ram_dump.field_offset('struct ftrace_event_field', 'link') name_str = ram_dump.read_cstring(name, 512) event_id = ram_dump.read_word(ftrace_list + event_offset + type_offset) fmt = ram_dump.read_word(ftrace_list + fmt_offset) fmt_str = ram_dump.read_cstring(fmt, 2048) self.formats_out.write("name: {0}\n".format(name_str)) self.formats_out.write("ID: {0}\n".format(event_id)) self.formats_out.write("format:\n") list_walker = llist.ListWalker(ram_dump, common_field_list, field_next_offset) list_walker.walk_prev(common_field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") event_class = ram_dump.read_word(ftrace_list + class_offset) field_list = event_class + fields_offset list_walker = llist.ListWalker(ram_dump, field_list, field_next_offset) list_walker.walk_prev(field_list, self.ftrace_field_func, ram_dump) self.formats_out.write("\n") self.formats_out.write("print fmt: {0}\n".format(fmt_str)) def collect_ftrace_format(self, ram_dump): formats = os.path.join('qtf', 'map_files', 'formats.txt') formats_out = ram_dump.open_file(formats) self.formats_out = formats_out ftrace_events_list = ram_dump.address_of('ftrace_events') next_offset = ram_dump.field_offset('struct ftrace_event_call', 'list') list_walker = llist.ListWalker(ram_dump, ftrace_events_list, next_offset) list_walker.walk_prev(ftrace_events_list, self.ftrace_events_func, ram_dump) self.formats_out.close def parse_qtf(self, ram_dump): out_dir = ram_dump.outdir if platform.system() != 'Windows': return qtf_path = ram_dump.qtf_path if qtf_path is None: try: import local_settings try: qtf_path = local_settings.qtf_path except AttributeError as e: print_out_str("attribute qtf_path in local_settings.py looks bogus. Please see README.txt") print_out_str("Full message: %s" % e.message) return except ImportError: print_out_str("missing qtf_path local_settings.") print_out_str("Please see the README for instructions on setting up local_settings.py") return if qtf_path is None: print_out_str("!!! Incorrect path for qtf specified.") print_out_str("!!! Please see the README for instructions on setting up local_settings.py") return if not os.path.exists(qtf_path): print_out_str("!!! qtf_path {0} does not exist! Check your settings!".format(qtf_path)) return if not os.access(qtf_path, os.X_OK): print_out_str("!!! No execute permissions on qtf path {0}".format(qtf_path)) return if os.path.getsize(os.path.join(out_dir, 'tmc-etf.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etf.bin') elif os.path.getsize(os.path.join(out_dir, 'tmc-etr.bin')) > 0: trace_file = os.path.join(out_dir, 'tmc-etr.bin') else: return port = None server_proc = None qtf_success = False max_tries = 3 qtf_dir = os.path.join(out_dir, 'qtf') workspace = os.path.join(qtf_dir, 'qtf.workspace') qtf_out = os.path.join(out_dir, 'qtf.txt') chipset = 'msm' + str(ram_dump.hw_id) hlos = 'LA' # Resolve any port collisions with other running qtf_server instances for tries in range(max_tries): port = random.randint(12000, 13000) server_proc = subprocess.Popen( [qtf_path, '-s', '{0}'.format(port)], stderr=subprocess.PIPE) time.sleep(1) server_proc.poll() if server_proc.returncode == 1: server_proc.terminate() continue else: qtf_success = True break if not qtf_success: server_proc.terminate() print_out_str('!!! Could not open a QTF server instance with a ' 'unique port (last port tried: ' '{0})'.format(str(port))) print_out_str('!!! Please kill all currently running qtf_server ' 'processes and try again') return subprocess.call('{0} -c {1} new workspace {2} {3} {4}'.format(qtf_path, port, qtf_dir, chipset, hlos)) self.collect_ftrace_format(ram_dump) subprocess.call('{0} -c {1} open workspace {2}'.format(qtf_path, port, workspace)) subprocess.call('{0} -c {1} open bin {2}'.format(qtf_path, port, trace_file)) subprocess.call('{0} -c {1} stream trace table {2}'.format(qtf_path, port, qtf_out)) subprocess.call('{0} -c {1} close'.format(qtf_path, port)) subprocess.call('{0} -c {1} exit'.format(qtf_path, port)) server_proc.communicate('quit') def parse_dcc(self, ram_dump): out_dir = ram_dump.outdir dcc_parser_path = os.path.join(os.path.dirname(__file__), '..', 'dcc_parser', 'dcc_parser.py') if dcc_parser_path is None: print_out_str("!!! Incorrect path for DCC specified.") return if not os.path.exists(dcc_parser_path): print_out_str("!!! dcc_parser_path {0} does not exist! Check your settings!".format(dcc_parser_path)) return if os.path.getsize(os.path.join(out_dir, 'sram.bin')) > 0: sram_file = os.path.join(out_dir, 'sram.bin') else: return p = subprocess.Popen([sys.executable, dcc_parser_path, '-s', sram_file, '--out-dir', out_dir], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) print_out_str('--------') print_out_str(p.communicate()[0]) 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', MAX_NUM_ENTRIES) self.dump_data_id_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( 'msm_dump_data_ids', MAX_NUM_ENTRIES) 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_TLB + i] = 'MSM_DUMP_DATA_L1_INST_TLB' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_L1_DATA_TLB + i] = 'MSM_DUMP_DATA_L1_DATA_TLB' 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_L2_CACHE + i] = 'MSM_DUMP_DATA_L2_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' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_LOG_BUF] = 'MSM_DUMP_DATA_LOG_BUF' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_LOG_BUF_FIRST_IDX] = 'MSM_DUMP_DATA_LOG_BUF_FIRST_IDX' self.dump_data_id_lookup_table[ client.MSM_DUMP_DATA_L2_TLB] = 'MSM_DUMP_DATA_L2_TLB' 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.address_of('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_name = ram_dump.read_cstring(client_addr + dump_data_name_offset, ram_dump.sizeof('((struct msm_dump_data *)0x0)->name'), 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} Source: {3}'.format( client_name, dump_data_version, dump_data_magic, dump_data_name)) 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_version, dump_data_addr, dump_data_addr + dump_data_len, client_id, ram_dump) self.qdss.dump_all(ram_dump) if ram_dump.qtf: self.parse_qtf(ram_dump) if ram_dump.dcc: self.parse_dcc(ram_dump)