diff --git a/linux-ramdump-parser-v2/debug_image_v2.py b/linux-ramdump-parser-v2/debug_image_v2.py index ca588acd15977366d4c8bee669920a899f2701f9..7494ef84bec6b6d34529c184a1f9d3da720e06fd 100644 --- a/linux-ramdump-parser-v2/debug_image_v2.py +++ b/linux-ramdump-parser-v2/debug_image_v2.py @@ -35,6 +35,7 @@ from fcmdump import FCM_Dump MEMDUMPV2_MAGIC = 0x42445953 MAX_NUM_ENTRIES = 0x150 +IMEM_OFFSET_MEM_DUMP_TABLE = 0x3f010 class client(object): MSM_DUMP_DATA_CPU_CTX = 0x00 @@ -598,6 +599,40 @@ class DebugImage_v2(): results.append((client_name, client_id,client_table[client_name], entry_pa_addr,end_addr)) return results + class MsmDumpTable(object): + def __init__(self): + self.name = "Anon" + self.phys_addr = 0x0 + self.version = 0x0 + self.num_entries = 0x0 + + """ Create an instance of MsmDumpTable, or None on error """ + def validateMsmDumpTable(self, ram_dump, name, table_phys): + if table_phys is None: + print_out_str('debug_image.py: Table {}: Unable to read dump table base address'.format(name)) + return None + + version = ram_dump.read_structure_field( + table_phys, 'struct msm_dump_table', 'version', + virtual = False) + if version is None: + print_out_str('Table {}: Version is bogus! Can\'t parse debug image'.format(name)) + return None + + num_entries = ram_dump.read_structure_field( + table_phys, 'struct msm_dump_table', 'num_entries', + virtual = False) + if num_entries is None or num_entries > 100: + print_out_str('Table {}: num_entries is bogus! Can\'t parse debug image'.format(name)) + return None + + table = self.MsmDumpTable() + table.name = name + table.phys_addr = table_phys + table.version = version + table.num_entries = num_entries + return table + def parse_dump_v2(self, ram_dump): self.dump_type_lookup_table = ram_dump.gdbmi.get_enum_lookup_table( 'msm_dump_type', 2) @@ -674,32 +709,34 @@ class DebugImage_v2(): 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') + """ + Some multi-guest hypervisor systems override the imem location + with a table for a crashed guest. So the value from IMEM may + not match the value saved in the linux variable 'memdump'. + """ + table_phys = ram_dump.read_word( + ram_dump.board.imem_start + IMEM_OFFSET_MEM_DUMP_TABLE, + virtual = False) + root_table = self.validateMsmDumpTable(ram_dump, "IMEM", table_phys) + + if root_table is None: + table_phys = ram_dump.read_structure_field( + 'memdump', 'struct msm_memory_dump', 'table_phys') + root_table = self.validateMsmDumpTable(ram_dump, "RAM", table_phys) + + if root_table is None: 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)) + root_table.version >> 20, root_table.version & 0xFFFFF, root_table.num_entries)) print_out_str('--------') - for i in range(0, mem_table_num_entry): - this_entry = mem_dump_table + dump_table_entry_offset + \ + for i in range(0, root_table.num_entries): + this_entry = root_table.phys_addr + 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) + entry_id = ram_dump.read_u32(this_entry + dump_entry_id_offset, virtual = False) + entry_type = ram_dump.read_u32(this_entry + dump_entry_type_offset, virtual = False) + entry_addr = ram_dump.read_word(this_entry + dump_entry_addr_offset, virtual = False) if entry_id < 0 or entry_id > len(self.dump_table_id_lookup_table): print_out_str( diff --git a/linux-ramdump-parser-v2/ramdump.py b/linux-ramdump-parser-v2/ramdump.py index 9fbabf750172e4b0eaf361c5d774a66542f4b203..107243538774285f778d7b4a2b6b202adc655082 100644 --- a/linux-ramdump-parser-v2/ramdump.py +++ b/linux-ramdump-parser-v2/ramdump.py @@ -51,7 +51,9 @@ extra_mem_file_names = ['EBI1CS1.BIN', 'DDRCS1.BIN', 'ebi1_cs1.bin', 'DDRCS1_5.BIN'] DDR_FILE_NAMES = ['DDRCS0.BIN', 'DDRCS1.BIN', 'DDRCS0_0.BIN', - 'DDRCS1_0.BIN', 'DDRCS0_1.BIN', 'DDRCS1_1.BIN'] + 'DDRCS1_0.BIN', 'DDRCS0_1.BIN', 'DDRCS1_1.BIN', + 'DDR_0.BIN', 'DDR_1.BIN', 'DDR_2.BIN', 'DDR_3.BIN', + 'RESET_INFO.BIN'] OTHER_DUMP_FILE_NAMES = ['PIMEM.BIN', 'OCIMEM.BIN','md_shared_imem.BIN', 'md_smem_info.BIN'] RAM_FILE_NAMES = set(DDR_FILE_NAMES + @@ -1213,6 +1215,7 @@ class RamDump(): self.kaslr_addr = board.kaslr_addr else: self.kaslr_addr = None + self.board = board return True def resolve_virt(self, virt_or_name): @@ -1491,19 +1494,18 @@ class RamDump(): fn = self.read_u32 if self.sizeof('void *') == 4 else self.read_u64 return fn(addr_or_name, virtual, cpu) - def read_structure_field(self, addr_or_name, struct_name, field): + def read_structure_field(self, addr_or_name, struct_name, field, virtual=True): """reads a 4 or 8 byte field from a structure""" size = self.sizeof("(({0} *)0)->{1}".format(struct_name, field)) - virt = self.resolve_virt(addr_or_name) - if virt is None or size is None: + addr = self.resolve_virt(addr_or_name) + if addr is None or size is None: return None + addr += self.field_offset(struct_name, field) if size == 4: - return self.read_u32(virt + self.field_offset(struct_name, - field)) + return self.read_u32(addr, virtual) if size == 8: - return self.read_u64(virt + self.field_offset(struct_name, - field)) + return self.read_u64(addr, virtual) return None def read_structure_cstring(self, addr_or_name, struct_name, field,