def find_mm(self, ramdump): thread_addr = None offset_comm = ramdump.field_offset('struct task_struct', 'comm') for task in ramdump.for_each_process(): task_name = cleanupString( ramdump.read_cstring(task + offset_comm, 16)) if task_name == 'logd': for thread in ramdump.for_each_thread(task): thread_name = cleanupString( ramdump.read_cstring(thread + offset_comm, 16)) if thread_name == 'logd.writer': thread_addr = thread break break if not thread_addr: print_out_str("!!!No logd.writer service found !\n") return mm_addr = ramdump.read_structure_field(thread_addr, 'struct task_struct', 'mm') pgd_addr = ramdump.read_structure_field(mm_addr, 'struct mm_struct', 'pgd') pgd_addr = ramdump.virt_to_phys(pgd_addr) self.mmu = type(ramdump.mmu)(ramdump, pgd_addr) self.mm_addr = mm_addr
def dump_args(self, ramdump, mm): names = ( ("env_start", "env_end"), ("arg_start", "arg_end"), ("start_stack", ""), ("start_brk", "brk"), ("start_data", "end_data"), ("mmap_base", ""), ("start_code", "end_code"), ) print_out_str("{:10}\t{:8}\t{:8}".format("name", "virt", "phys")) print_out_str("----------------------------------") for start, end in names: if len(end) > 0: virt = ramdump.read_structure_field(mm, 'struct mm_struct', end) phys = self.mmu.virt_to_phys(virt) or 0 print_out_str("{:10}\t0x{:08x}\t0x{:08x}".format( end, virt, phys)) if len(start) > 0: virt = ramdump.read_structure_field(mm, 'struct mm_struct', start) phys = self.mmu.virt_to_phys(virt) or 0 print_out_str("{:10}\t0x{:08x}\t0x{:08x}".format( start, virt, phys)) print_out_str("----------------------------------")
def parse(self): if not self.ramdump.is_config_defined('CONFIG_FUNCTION_TRACER') or not self.ramdump.is_config_defined('CONFIG_HAVE_FUNCTION_TRACER'): print_out_str ("function tracer is not enabled") return self.getsrd() for core in range(0, self.srd_ncpu): self.readtrace(self.srd_r_pa, core)
def parse(self): if self.ramdump.Is_Dakota(): regs = DebugImage_v2() client_start = 0x87b000e0 client_end = 0x500 client_name = "Dump" numcpus = self.ramdump.get_num_cpus() regs.parse_cpu_ctx(numcpus - 1, client_start, client_end, 1, self.ramdump) return if self.ramdump.Is_Hawkeye(): regs = DebugImage_v3() client_start = 0x08600658 client_end = 0x500 client_name = "Dump" regs.parse_cpu_ctx(3, client_start, client_end, 1, self.ramdump) return # 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
def parse(self): self.output_file = self.ramdump.open_file('timerlist.txt') self.get_timer_list() self.output_file.close() print_out_str("--- Wrote the output to timerlist.txt")
def parse(self): self.output_file = self.ramdump.open_file('thermal_info.txt') self.tmdev_data(self.ramdump) self.output_file.close() print_out_str("--- Wrote the output to thermal_info.txt")
def print_regs(self, outfile, ramdump): for reg_name, t32_name, print_pc in tzbsp_register_names: if print_pc: modname = None symname = None symtab_st_size = None offset = None a = ramdump.unwind_lookup(self.regs[reg_name]) if a is not None and len(a) > 3: symname, offset, modname, symtab_st_size = a if (modname is not None and symtab_st_size is not None): pc_string = '[{0}+0x{1:x}/0x{3:x}] <{2}.ko>'.format( symname, offset, modname, symtab_st_size) else: pc_string = '[{0}+0x{1:x}/0x{2:x}]'.format( symname, offset, symtab_st_size) elif a is not None: symname, offset, modname = a if (modname is not None): pc_string = '[{0}+0x{1:x}] <{2}.ko>'.format( symname, offset, modname) else: pc_string = '[{0}+0x{1:x}]'.format(symname, offset) else: pc_string = '' else: pc_string = '' print_out_str(' {0} = 0x{1:08x} {2}'.format( reg_name, self.regs[reg_name], pc_string)) if t32_name is not None: outfile.write('r.s {0} 0x{1:x}\n'.format( t32_name, self.regs[reg_name]))
def parse(self): try: crashtool = local_settings.crashtool except AttributeError: print_out_str("crashtool is missing from local-settings.py") crashtool = "crash" crashargs = [crashtool] kaslr_offset = self.ramdump.get_kaslr_offset() if kaslr_offset != 0: crashargs.append("--kaslr {0}".format(hex(kaslr_offset))) if self.ramdump.kimage_voffset is not None: kimagevoff = "kimage_voffset={0}".format( hex(self.ramdump.kimage_voffset).replace('L','')) crashargs.append("--machdep {0}".format(kimagevoff)) crashargs.append(os.path.abspath(self.ramdump.vmlinux)) dumps = [] for ram in self.ramdump.ebi_files: ebi_path = os.path.abspath(ram[3]) dumps.append('{0}@0x{1:x}'.format(ebi_path, ram[1])) crashargs.append(",".join(dumps)) with self.ramdump.open_file("launch_crash.sh") as f: f.write("#!/bin/sh\n\n") f.write(" ".join(crashargs)) f.write("\n") os.chmod(f.name, stat.S_IRWXU) print_out_str("Run Crash Utility by exec: '{0}'".format(f.name))
def parse(self): if not self.ramdump.is_config_defined('CONFIG_SLUB_DEBUG'): print_out_str ("slub_debug_on is not enabled") return slab_out = self.ramdump.open_file('slabsummary.txt') self.print_slab_summary(slab_out) slab_out.close()
def print_dbgui_registers(self, ram_dump): if self.dbgui_start is None: print_out_str( "!!!DBGUI address has not been set! I can't continue!") return print_out_str('Now printing DBGUI registers to file') dbgui_out = ram_dump.open_file('dbgui.txt') for a, b in dbgui_registers.iteritems(): offset, name = b dbgui_out.write('{0} ({1}): {2:x}\n'.format( a, name, ram_dump.read_u32(self.dbgui_start + offset, False))) addr = ram_dump.read_word(ram_dump.address_of('dbgui_drvdata')) addr_offset_offset = ram_dump.field_offset('struct dbgui_drvdata', 'addr_offset') data_offset_offset = ram_dump.field_offset('struct dbgui_drvdata', 'data_offset') size_offset = ram_dump.field_offset('struct dbgui_drvdata', 'size') addr_offset = ram_dump.read_u32(addr + addr_offset_offset, True) data_offset = ram_dump.read_u32(addr + data_offset_offset, True) size = ram_dump.read_u32(addr + size_offset, True) for i in range(0, size): dbgui_out.write('ADDR_{0} ({1:x}) : {2:x}\n'.format( i, ram_dump.read_u32(self.dbgui_start + addr_offset + (4 * i), False), ram_dump.read_u32(self.dbgui_start + data_offset + (4 * i), False))) dbgui_out.close()
def walk_prev(self, node_addr, func, *args): """Walk the linked list starting at `node_addr' previous node and traverse the list in reverse order, calling `func' on each node. `func' will be passed the current node and *args, if given. """ node_addr = self.ram_dump.read_word( node_addr + self.ram_dump.field_offset('struct list_head', 'prev')) while True: if node_addr == 0: break funcargs = [node_addr - self.list_elem_offset] + list(args) func(*funcargs) prev_node_addr = node_addr + self.ram_dump.field_offset( 'struct list_head', 'prev') prev_node = self.ram_dump.read_word(prev_node_addr) if prev_node == self.last_node: break if prev_node in self.seen_nodes: print_out_str( '[!] WARNING: Cycle found in attach list. List is corrupted!' ) break node_addr = prev_node self.seen_nodes.append(node_addr)
def find_panic(ramdump, addr_stack, thread_task_name): if ramdump.arm64: stack_size = 0x4000 increment = 8 else: stack_size = 0x2000 increment = 4 for i in range(addr_stack, addr_stack + stack_size, increment): if ramdump.arm64: pc = ramdump.read_word(i + 8) - 4 fp = ramdump.read_word(i) spx = i + 16 lr = 0 else: pc = ramdump.read_word(i) lr = ramdump.read_word(i + 4) spx = i + 4 fp = 0 l = ramdump.unwind_lookup(pc) if l is not None: s, offset = l if s == 'panic': print_out_str('Faulting process found! Name {0})'.format(thread_task_name)) ramdump.unwind.unwind_backtrace(spx, fp, pc, lr, '') regspanic = ramdump.open_file('regs_panic.cmm') if ramdump.arm64: regspanic.write('r.s pc 0x{0:x}\n'.format(pc)) regspanic.write('r.s sp 0x{0:x}\n'.format(spx)) else: regspanic.write('r.s pc 0x{0:x}\n'.format(pc)) regspanic.write('r.s r13 0x{0:x}\n'.format(i + 4)) regspanic.close() return True return False
def save_l1_dump(ram_dump, cache_base, size): with ram_dump.open_file('l1_cache_dump.bin') as cache_file: for i in range(0, size): val = ram_dump.read_byte(cache_base + i, False) cache_file.write(struct.pack('<B', val)) print_out_str('--- Wrote cache dump to l1_cache_dump.bin')
def save_etf_bin(self, ram_dump): tmc_etf = ram_dump.open_file('tmc-etf.bin') if self.tmc_etf_start is None or self.etf_start is None: print_out_str('!!! ETF was not the current sink!') tmc_etf.close() return 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_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): for i in range(0, rsz): val = ram_dump.read_byte(self.etf_start + i, False) tmc_etf.write(struct.pack('<B', val)) else: print_out_str('!!! ETF was not the current sink!') tmc_etf.close()
def run(self): """ Main """ if self.ramdump.arm64 is None: print_out_str('[Caution] this script supports on ARM64') return False if self.ramdump.wlan == "INTEGRATED": print_out_str('self.wlan doen\'t exist, skip') else: print_out_str('self.wlan exist {}'.format(self.ramdump.wlan)) self.wlan_path = self.ramdump.wlan if self.get_sections_of_wlan() is False: print_out_str('wlan.ko is not loaded.') return False else: print_out_str('** Find WLAN Module **') self.load_wlan_ko() self.get_wmi_command_log_buffer() self.get_host_wmi_command_tx_cmp_buf() self.get_host_wmi_event_buf() self.get_host_wmi_rx_event_buf() self.get_host_extract_log() return True
def set_sym_path(self, sym_path): if os.path.isfile(sym_path): self.sym_path = sym_path return True else: print_out_str('sym_path: ' + sym_path + ' not valid or file doesn\'t exist') return False
def print_regs(self, outfile, ramdump): if ramdump.arm64: register_names = sysdbg_cpu64_register_names[self.version] else: register_names = sysdbg_cpu32_register_names[self.version] for reg_name, t32_name, print_pc in register_names: if re.match('(.*)reserved(.*)', reg_name): continue 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: if reg_name.startswith('cpu_state_'): continue outfile.write( 'r.s {0} 0x{1:x}\n'.format(t32_name, self.regs[reg_name]))
def walk(self, node_addr, func, *args): """Walk the linked list starting at `node_addr', calling `func' on each node. `func' will be passed the current node and *args, if given. """ if self.is_empty() == True: return while True: if node_addr == 0: break funcargs = [node_addr - self.list_elem_offset] + list(args) func(*funcargs) next_node_addr = node_addr + self.ram_dump.field_offset("struct list_head", "next") next_node = self.ram_dump.read_word(next_node_addr) if next_node == self.last_node: break if next_node in self.seen_nodes: print_out_str("[!] WARNING: Cycle found in attach list. List is corrupted!") break node_addr = next_node self.seen_nodes.append(node_addr)
def read_tz_offset(self): if self.tz_addr == 0: print_out_str( 'No TZ address was given, cannot read the magic value!') return None else: return self.read_word(self.tz_addr, False)
def walk(self, node_addr, func, *args): """Walk the linked list starting at `node_addr', calling `func' on each node. `func' will be passed the current node and *args, if given. """ if self.is_empty() == True: return while True: if node_addr == 0: break funcargs = [node_addr - self.list_elem_offset] + list(args) func(*funcargs) next_node_addr = node_addr + self.ram_dump.field_offset( 'struct list_head', 'next') next_node = self.ram_dump.read_word(next_node_addr) if next_node == self.last_node: break if next_node in self.seen_nodes: print_out_str( '[!] WARNING: Cycle found in attach list. List is corrupted!' ) break node_addr = next_node self.seen_nodes.append(node_addr)
def unwind_frame_tables(self, frame, trace=False): low = frame.sp high = ((low + (self.ramdump.thread_size - 1)) & \ ~(self.ramdump.thread_size - 1)) + self.ramdump.thread_size idx = self.search_idx(frame.pc) if (idx is None): if trace: print_out_str("can't find %x" % frame.pc) return -1 ctrl = self.UnwindCtrlBlock() ctrl.vrs[FP] = frame.fp ctrl.vrs[SP] = frame.sp ctrl.vrs[LR] = frame.lr ctrl.vrs[PC] = 0 if (idx[1] == 1): return -1 elif ((idx[1] & 0x80000000) == 0): ctrl.insn = self.prel31_to_addr(idx[2] + 4) elif (idx[1] & 0xff000000) == 0x80000000: ctrl.insn = idx[2] + 4 else: print_out_str('not supported') return -1 val = self.ramdump.read_word(ctrl.insn) if ((val & 0xff000000) == 0x80000000): ctrl.byte = 2 ctrl.entries = 1 elif ((val & 0xff000000) == 0x81000000): ctrl.byte = 1 ctrl.entries = 1 + ((val & 0x00ff0000) >> 16) else: return -1 while (ctrl.entries > 0): urc = self.unwind_exec_insn(ctrl, trace) if (urc < 0): return urc if (ctrl.vrs[SP] < low or ctrl.vrs[SP] >= high): return -1 if (ctrl.vrs[PC] == 0): ctrl.vrs[PC] = ctrl.vrs[LR] # check for infinite loop */ if (frame.pc == ctrl.vrs[PC]): return -1 frame.fp = ctrl.vrs[FP] frame.sp = ctrl.vrs[SP] frame.lr = ctrl.vrs[LR] frame.pc = ctrl.vrs[PC] return 0
def walk_prev(self, node_addr, func, *args): """Walk the linked list starting at `node_addr' previous node and traverse the list in reverse order, calling `func' on each node. `func' will be passed the current node and *args, if given. """ node_addr = self.ram_dump.read_word(node_addr + self.ram_dump.field_offset('struct list_head', 'prev')) while True: if node_addr == 0: break funcargs = [node_addr - self.list_elem_offset] + list(args) func(*funcargs) prev_node_addr = node_addr + self.ram_dump.field_offset('struct list_head', 'prev') prev_node = self.ram_dump.read_word(prev_node_addr) if prev_node == self.last_node: break if prev_node in self.seen_nodes: print_out_str( '[!] WARNING: Cycle found in attach list. List is corrupted!') break node_addr = prev_node self.seen_nodes.append(node_addr)
def walk_workers(self, worker_addr, state): worker_task_offset = self.ramdump.field_offset('struct worker', 'task') offset_comm = self.ramdump.field_offset('struct task_struct', 'comm') current_work_offset = self.ramdump.field_offset( 'struct worker', 'current_work') work_func_offset = self.ramdump.field_offset('struct work_struct', 'func') worker_task_addr = self.ramdump.read_word( worker_addr + worker_task_offset) taskname = self.ramdump.read_cstring( worker_task_addr + offset_comm, 16) current_work_addr = self.ramdump.read_word( worker_addr + current_work_offset) try: phys = self.ramdump.virt_to_phys(current_work_func) current_work_func = self.ramdump.read_word( current_work_addr + work_func_offset) wname = self.ramdump.unwind_lookup(current_work_func) if wname is not None: worker_name, a = wname else: worker_name = 'Worker at 0x{0:x}'.format( current_work_func) except: worker_name = '(None)' print_out_str( '{2} Workqueue worker: {0} current_work: {1}'.format(taskname, worker_name, state))
def find_panic(ramdump, addr_stack, thread_task_name): if ramdump.arm64: stack_size = 0x4000 increment = 8 else: stack_size = 0x2000 increment = 4 for i in range(addr_stack, addr_stack + stack_size, increment): if ramdump.arm64: pc = ramdump.read_word(i + 8) - 4 fp = ramdump.read_word(i) spx = i + 16 lr = 0 else: pc = ramdump.read_word(i) lr = ramdump.read_word(i + 4) spx = i + 4 fp = 0 l = ramdump.unwind_lookup(pc) if l is not None: s, offset = l if s == 'panic': print_out_str('Faulting process found! Name {0})'.format( thread_task_name)) ramdump.unwind.unwind_backtrace(spx, fp, pc, lr, '') regspanic = ramdump.open_file('regs_panic.cmm') if ramdump.arm64: regspanic.write('r.s pc 0x{0:x}\n'.format(pc)) regspanic.write('r.s sp 0x{0:x}\n'.format(spx)) else: regspanic.write('r.s pc 0x{0:x}\n'.format(pc)) regspanic.write('r.s r13 0x{0:x}\n'.format(i + 4)) regspanic.close() return True return False
def unwind_backtrace(self, sp, fp, pc, lr, extra_str='', out_file=None): offset = 0 frame = self.Stackframe(fp, sp, lr, pc) frame.fp = fp frame.sp = sp frame.lr = lr frame.pc = pc while True: where = frame.pc offset = 0 if frame.pc is None: break r = self.ramdump.unwind_lookup(frame.pc) if r is None: symname = 'UNKNOWN' offset = 0x0 else: symname, offset = r pstring = ( extra_str + '[<{0:x}>] {1}+0x{2:x}'.format(frame.pc, symname, offset)) if out_file: out_file.write(pstring + '\n') else: print_out_str(pstring) urc = self.unwind_frame(frame) if urc < 0: break
def read_string(self, address, format_string, virtual=True, trace=False, cpu=None): addr = address per_cpu_string = '' if virtual: if cpu is not None: pcpu_offset = self.per_cpu_offset(cpu) address += pcpu_offset per_cpu_string = ' with per-cpu offset of ' + hex(pcpu_offset) addr = self.virt_to_phys(address) if trace: if addr is not None: print_out_str('reading from phys {0:x}{1}'.format( addr, per_cpu_string)) s = self.read_physical(addr, struct.calcsize(format_string), trace) if (s is None) or (s == ''): if trace and addr is not None: print_out_str( 'address {0:x} failed hard core (v {1} t{2})'.format( addr, virtual, trace)) return None return struct.unpack(format_string, s)
def parse_long_form_tables(dump, d): fname = 'msm_iommu_domain_%02d.txt' % (d.domain_num) with dump.open_file(fname) as outfile: print_out_str('LPAE Iommu page tables: ' + fname) t0sz = 0 mmu = Armv7LPAEMMU(dump, d.pg_table, t0sz, virt_for_fl=True) redirect = 'OFF' if d.redirect is None: redirect = 'UNKNOWN' elif d.redirect > 0: redirect = 'ON' iommu_context = ' '.join('%s (%s)' % (name, num) for (name, num) in d.ctx_list) iommu_context = iommu_context or 'None attached' outfile.write( 'IOMMU Context: %s. Domain: %s (%d) [L2 cache redirect for page tables is %s]\n' % (iommu_context, d.client_name, d.domain_num, redirect)) outfile.write( '[VA Start -- VA End ] [Size ] [PA Start -- PA End ] [Attributes][Page Table Entry Size]\n' ) if d.pg_table == 0: outfile.write('No Page Table Found. (Probably a secure domain)\n') else: mappings = get_flat_mappings(d, mmu) print_lpae_mappings(get_coalesced_mappings(mappings), outfile) outfile.write('\n-------------\nRAW Dump\n') outfile.write('Raw: ' + str(d) + '\n') print_lpae_mappings(mappings, outfile)
def parse_long_form_tables(dump, d): fname = 'msm_iommu_domain_%02d.txt' % (d.domain_num) with dump.open_file(fname) as outfile: print_out_str('LPAE Iommu page tables: ' + fname) t0sz = 0 mmu = Armv7LPAEMMU(dump, d.pg_table, t0sz, virt_for_fl=True) redirect = 'OFF' if d.redirect is None: redirect = 'UNKNOWN' elif d.redirect > 0: redirect = 'ON' iommu_context = ' '.join('%s (%s)' % (name, num) for (name, num) in d.ctx_list) iommu_context = iommu_context or 'None attached' outfile.write('IOMMU Context: %s. Domain: %s (%d) [L2 cache redirect for page tables is %s]\n' % ( iommu_context, d.client_name, d.domain_num, redirect)) outfile.write( '[VA Start -- VA End ] [Size ] [PA Start -- PA End ] [Attributes][Page Table Entry Size]\n') if d.pg_table == 0: outfile.write( 'No Page Table Found. (Probably a secure domain)\n') else: mappings = get_flat_mappings(d, mmu) print_lpae_mappings(get_coalesced_mappings(mappings), outfile) outfile.write('\n-------------\nRAW Dump\n') outfile.write('Raw: ' + str(d) + '\n') print_lpae_mappings(mappings, outfile)
def parse(self): self.output_file = self.ramdump.open_file('cpr3_info.txt') self.get_cpr() self.get_kryo() for i in self.output: self.output_file.write(i) print_out_str("--- Wrote the output to cpr3_info.txt") self.output_file.close()
def parse(self): saved_config = self.ramdump.open_file('kconfig.txt') for l in self.ramdump.config: saved_config.write(l + '\n') saved_config.close() print_out_str('---wrote saved kernel config to kconfig.txt')
def walk_stackframe_generic(self, frame): while True: symname = self.ramdump.addr_to_symbol(frame.pc) print_out_str(symname) ret = self.unwind_frame_generic(frame) if ret < 0: break
def parse(self): self.output_file = self.ramdump.open_file('DDRCacheCompare.txt') self.compare_magic() self.corruptionchecker() self.output_file.close() print_out_str("--- Wrote the output to DDRCacheCompare.txt")
def read_u16(self, address, virtual=True, trace=False, cpu=None): if trace: print_out_str('reading {0:x}'.format(address)) s = self.read_string(address, '<H', virtual, trace, cpu) if s is None: return None else: return s[0]
def parse(self): if not self.ramdump.is_config_defined("CONFIG_MSM_CACHE_DUMP"): print_out_str("!!! Cache dumping was not enabled. No cache will be dumped") return cache_base_addr = self.ramdump.address_of("l2_dump") cache_base = self.ramdump.read_word(cache_base_addr) parse_cache_dump(self.ramdump, cache_base)
def print_irq_state_sparse_irq(self, ram_dump): h_irq_offset = ram_dump.field_offset('struct irq_desc', 'handle_irq') irq_num_offset = ram_dump.field_offset('struct irq_data', 'irq') irq_data_offset = ram_dump.field_offset('struct irq_desc', 'irq_data') irq_count_offset = ram_dump.field_offset('struct irq_desc', 'irq_count') irq_chip_offset = ram_dump.field_offset('struct irq_data', 'chip') irq_action_offset = ram_dump.field_offset('struct irq_desc', 'action') action_name_offset = ram_dump.field_offset('struct irqaction', 'name') kstat_irqs_offset = ram_dump.field_offset('struct irq_desc', 'kstat_irqs') chip_name_offset = ram_dump.field_offset('struct irq_chip', 'name') cpu_str = '' irq_desc_tree = ram_dump.address_of('irq_desc_tree') nr_irqs = ram_dump.read_int(ram_dump.address_of('nr_irqs')) for i in ram_dump.iter_cpus(): cpu_str = cpu_str + '{0:10} '.format('CPU{0}'.format(i)) print_out_str('{0:4} {1} {2:30} {3:15} {4:20}'.format( 'IRQ', cpu_str, 'Name', 'Chip', 'IRQ Structure')) if nr_irqs > 50000: return for i in range(0, nr_irqs): irq_desc = self.radix_tree_lookup_element(ram_dump, irq_desc_tree, i) if irq_desc is None: continue irqnum = ram_dump.read_int(irq_desc + irq_data_offset + irq_num_offset) irqcount = ram_dump.read_int(irq_desc + irq_count_offset) action = ram_dump.read_word(irq_desc + irq_action_offset) kstat_irqs_addr = ram_dump.read_word(irq_desc + kstat_irqs_offset) irq_stats_str = '' if kstat_irqs_addr is None: break for j in ram_dump.iter_cpus(): irq_statsn = ram_dump.read_int(kstat_irqs_addr, cpu=j) irq_stats_str = irq_stats_str + \ '{0:10} '.format('{0}'.format(irq_statsn)) chip = ram_dump.read_word(irq_desc + irq_data_offset + irq_chip_offset) chip_name_addr = ram_dump.read_word(chip + chip_name_offset) chip_name = ram_dump.read_cstring(chip_name_addr, 48) if action != 0: name_addr = ram_dump.read_word(action + action_name_offset) name = ram_dump.read_cstring(name_addr, 48) print_out_str( '{0:4} {1} {2:30} {3:15} v.v (struct irq_desc *)0x{4:<20x}' .format(irqnum, irq_stats_str, name, chip_name, irq_desc))
def parse(self) : out_path = self.ramdump.outdir saved_config = open(out_path+"/kconfig.txt","wb") for l in self.ramdump.config : saved_config.write(l+"\n") saved_config.close() print_out_str("---wrote saved kernel config to {0}/kconfig.txt".format(out_path))
def auto_parse(self, file_path): first_mem_path = None for f in first_mem_file_names: test_path = file_path + '/' + f if os.path.exists(test_path): first_mem_path = test_path break if first_mem_path is None: print_out_str('!!! Could not open a memory file. I give up') sys.exit(1) first_mem = open(first_mem_path, 'rb') # put some dummy data in for now self.ebi_files = [(first_mem, 0, 0xffff0000, first_mem_path)] if not self.get_hw_id(add_offset=False): return False base_addr = self.get_ddr_base_addr(file_path) if base_addr is not None: self.ebi_start = base_addr self.phys_offset = base_addr else: print_out_str('!!! WARNING !!! Using Static DDR Base Addresses.') first_mem_end = self.ebi_start + os.path.getsize(first_mem_path) - 1 self.ebi_files = [ (first_mem, self.ebi_start, first_mem_end, first_mem_path)] print_out_str( 'Adding {0} {1:x}--{2:x}'.format(first_mem_path, self.ebi_start, first_mem_end)) self.ebi_start = self.ebi_start + os.path.getsize(first_mem_path) for f in extra_mem_file_names: extra_path = file_path + '/' + f if os.path.exists(extra_path): extra = open(extra_path, 'rb') extra_start = self.ebi_start extra_end = extra_start + os.path.getsize(extra_path) - 1 self.ebi_start = extra_end + 1 print_out_str( 'Adding {0} {1:x}--{2:x}'.format(extra_path, extra_start, extra_end)) self.ebi_files.append( (extra, extra_start, extra_end, extra_path)) if self.imem_fname is not None: imemc_path = file_path + '/' + self.imem_fname if os.path.exists(imemc_path): imemc = open(imemc_path, 'rb') imemc_start = self.tz_start imemc_end = imemc_start + os.path.getsize(imemc_path) - 1 print_out_str( 'Adding {0} {1:x}--{2:x}'.format(imemc_path, imemc_start, imemc_end)) self.ebi_files.append( (imemc, imemc_start, imemc_end, imemc_path)) return True
def wait_for_completion_timeout(self, task, timeout): delay = 2.0 #while the process is still executing and we haven't timed-out yet while task.poll() is None and timeout > 0: time.sleep(delay) timeout -= delay if timeout <= 0: print_out_str("QTF command timed out") task.kill()
def parse(self): if not self.ramdump.is_config_defined('CONFIG_MSM_CACHE_DUMP'): print_out_str( '!!! Cache dumping was not enabled. No cache will be dumped') return cache_base_addr = self.ramdump.addr_lookup('l2_dump') cache_base = self.ramdump.read_word(cache_base_addr) parse_cache_dump(self.ramdump, cache_base)
def open_file(self, file_name, mode='wb'): file_path = os.path.join(self.outdir, file_name) f = None try: f = open(file_path, mode) except: print_out_str('Could not open path {0}'.format(file_path)) print_out_str('Do you have write/read permissions on the path?') sys.exit(1) return f
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(self): self.output_file = self.ramdump.open_file('ClockDumps.txt') self.get_clocks() self.printclocks('CLOCKS') self.get_clk_providers() self.printclocks('CLK_PROVIDERS') self.output_file.close() print_out_str("--- Wrote the output to ClockDumps.txt")
def print_irq_state_sparse_irq(self, ram_dump): h_irq_offset = ram_dump.field_offset('struct irq_desc', 'handle_irq') irq_num_offset = ram_dump.field_offset('struct irq_data', 'irq') irq_data_offset = ram_dump.field_offset('struct irq_desc', 'irq_data') irq_count_offset = ram_dump.field_offset( 'struct irq_desc', 'irq_count') irq_chip_offset = ram_dump.field_offset('struct irq_data', 'chip') irq_action_offset = ram_dump.field_offset('struct irq_desc', 'action') action_name_offset = ram_dump.field_offset('struct irqaction', 'name') kstat_irqs_offset = ram_dump.field_offset( 'struct irq_desc', 'kstat_irqs') chip_name_offset = ram_dump.field_offset('struct irq_chip', 'name') cpu_str = '' irq_desc_tree = ram_dump.address_of('irq_desc_tree') nr_irqs = ram_dump.read_int(ram_dump.address_of('nr_irqs')) for i in ram_dump.iter_cpus(): cpu_str = cpu_str + '{0:10} '.format('CPU{0}'.format(i)) print_out_str( '{0:4} {1} {2:30} {3:15} {4:20}'.format('IRQ', cpu_str, 'Name', 'Chip', 'IRQ Structure')) if nr_irqs > 50000: return for i in range(0, nr_irqs): irq_desc = self.radix_tree_lookup_element( ram_dump, irq_desc_tree, i) if irq_desc is None: continue irqnum = ram_dump.read_int(irq_desc + irq_data_offset + irq_num_offset) irqcount = ram_dump.read_int(irq_desc + irq_count_offset) action = ram_dump.read_word(irq_desc + irq_action_offset) kstat_irqs_addr = ram_dump.read_word(irq_desc + kstat_irqs_offset) irq_stats_str = '' if kstat_irqs_addr is None: break for j in ram_dump.iter_cpus(): irq_statsn = ram_dump.read_int(kstat_irqs_addr, cpu=j) irq_stats_str = irq_stats_str + \ '{0:10} '.format('{0}'.format(irq_statsn)) chip = ram_dump.read_word( irq_desc + irq_data_offset + irq_chip_offset) chip_name_addr = ram_dump.read_word(chip + chip_name_offset) chip_name = ram_dump.read_cstring(chip_name_addr, 48) if action != 0: name_addr = ram_dump.read_word(action + action_name_offset) name = ram_dump.read_cstring(name_addr, 48) print_out_str( '{0:4} {1} {2:30} {3:15} v.v (struct irq_desc *)0x{4:<20x}'.format(irqnum, irq_stats_str, name, chip_name, irq_desc))
def read_word(self, address, virtual=True, trace=False, cpu=None): if trace: print_out_str('reading {0:x}'.format(address)) if self.arm64: s = self.read_string(address, '<Q', virtual, trace, cpu) else: s = self.read_string(address, '<I', virtual, trace, cpu) if s is None: return None else: return s[0]
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 print_workqueue_state_3_10(self, ram_dump): cpu_worker_pools_addr = ram_dump.address_of('cpu_worker_pools') busy_hash_offset = ram_dump.field_offset( 'struct worker_pool', 'busy_hash') worker_entry_offset = ram_dump.field_offset('struct worker', 'entry') work_entry_offset = ram_dump.field_offset( 'struct work_struct', 'entry') work_hentry_offset = ram_dump.field_offset('struct worker', 'hentry') pool_idle_offset = ram_dump.field_offset( 'struct worker_pool', 'idle_list') worker_pool_size = ram_dump.sizeof('struct worker_pool') pending_work_offset = ram_dump.field_offset( 'struct worker_pool', 'worklist') hash_size = 2 ** self.ramdump.gdbmi.get_value_of('BUSY_WORKER_HASH_ORDER') s = '<' if ram_dump.arm64: pool_char = 'Q' else: pool_char = 'I' for a in range(0, hash_size): s = s + pool_char for i in ram_dump.iter_cpus(): busy_hash = [] worker_pool = cpu_worker_pools_addr + ram_dump.per_cpu_offset(i) print_out_str('\nCPU {0}'.format(i)) n_pools = self.ramdump.gdbmi.get_value_of('NR_STD_WORKER_POOLS') for k in range(0, n_pools): print_out_str('pool {0}'.format(k)) worker_pool_i = worker_pool + k * worker_pool_size busy_hashi = ram_dump.read_string( worker_pool_i + busy_hash_offset, s) for a in busy_hashi: busy_hash.append(a) for k in range(0, hash_size): next_busy_worker = busy_hash[k] if busy_hash[k] != 0: busy_list_walker = linux_list.ListWalker(ram_dump, next_busy_worker, work_hentry_offset) busy_list_walker.walk(next_busy_worker, self.walk_workers, 'BUSY') idle_list_addr = worker_pool_i + pool_idle_offset idle_list_walker = linux_list.ListWalker(ram_dump, idle_list_addr, worker_entry_offset) idle_list_walker.walk(self.ramdump.read_word(idle_list_addr), self.walk_workers, 'IDLE') worklist_addr = worker_pool_i + pending_work_offset pending_list = linux_list.ListWalker(ram_dump, worklist_addr, work_entry_offset) pending_list.walk(self.ramdump.read_word(worklist_addr), self.pending_list_walk)