From 8c11f4db4c6b2b6516059d1643d1e83922db8873 Mon Sep 17 00:00:00 2001 From: Dylan Hatch <dhatch@codeaurora.org> Date: Wed, 27 Jun 2018 10:36:53 -0700 Subject: [PATCH] ion_buffer_parse: outputs to ionproc.txt information about dmabufs organized by process. Ion buffer info printed, with buffers and processes sorted by size. Change-Id: I22480f99a26a36e29bfd99c05701aab1bbe8e2d6 Signed-off-by: Dylan Hatch <dhatch@codeaurora.org> --- .../parsers/ion_buffer_parse.py | 111 +++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py b/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py index 44f3167..bf47b17 100644 --- a/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py +++ b/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py @@ -53,7 +53,7 @@ def ion_buffer_info(self, ramdump, ion_info): "buffer information") return - ion_info.write("*****Prasing dma buf info for ion leak debugging*****\n\n") + ion_info.write("*****Parsing dma buf info for ion leak debugging*****\n\n") head_offset = ramdump.field_offset('struct dma_buf_list', 'head') head = ramdump.read_word(db_list + head_offset) list_node_offset = ramdump.field_offset('struct dma_buf', 'list_node') @@ -82,6 +82,114 @@ def ion_buffer_info(self, ramdump, ion_info): ion_info.write(str) +def get_bufs(task, bufs, ion_info, ramdump): + t_size = 0 + dma_buf_fops = ramdump.address_of('dma_buf_fops') + if dma_buf_fops is None: + ion_info.write("NOTE: 'dma_buf_fops' not found for file information\n") + return 0 + timekeeper = ramdump.address_of('shadow_timekeeper') + if timekeeper is None: + ion_info.write("NOTE: 'timekeeper' not found for timing information\n") + return 0 + + files_offset = ramdump.field_offset('struct task_struct', 'files') + fdt_offset = ramdump.field_offset('struct files_struct', 'fdt') + fd_offset = ramdump.field_offset('struct fdtable', 'fd') + max_fds_offset = ramdump.field_offset('struct fdtable', 'max_fds') + f_op_offset = ramdump.field_offset('struct file', 'f_op') + private_data_offset = ramdump.field_offset('struct file', 'private_data') + size_offset = ramdump.field_offset('struct dma_buf', 'size') + name_offset = ramdump.field_offset('struct dma_buf', 'name') + stime_offset = ramdump.field_offset('struct timekeeper', 'xtime_sec') + + if task is None: + return 0 + files = ramdump.read_pointer(task + files_offset) + if files is None: + return 0 + fdt = ramdump.read_pointer(files + fdt_offset) + if fdt is None: + return 0 + fd = ramdump.read_pointer(fdt + fd_offset) + max_fds = ramdump.read_halfword(fdt + max_fds_offset) + stime = ramdump.read_word(timekeeper + stime_offset) + ctime_offset = ramdump.field_offset('struct dma_buf', 'ctime') + if ctime_offset is not None: + ctime_offset += ramdump.field_offset('struct timespec', 'tv_sec') + for i in range(max_fds): + file = ramdump.read_pointer(fd + i*8) + if (file == 0): + continue + f_op = ramdump.read_pointer(file + f_op_offset) + if (f_op != dma_buf_fops): + continue + dmabuf = ramdump.read_pointer(file + private_data_offset) + size = ramdump.read_word(dmabuf + size_offset) + time = 0 + if ctime_offset is not None: + ctime = ramdump.read_word(dmabuf + ctime_offset) + time = stime - ctime + name = ramdump.read_word(dmabuf + name_offset) + name = ramdump.read_cstring(name, 48) + + item = [name, hex(size), bytes_to_KB(size), time] + if item not in bufs: + t_size = t_size + size + bufs.append(item) + bufs.sort(key=lambda item: -item[2]) + return t_size + + +def get_proc_bufs(task, bufs, ion_info, ramdump): + group_offset = ramdump.field_offset('struct task_struct', 'thread_group') + group_node = ramdump.read_word(task + group_offset) + size = 0; + curr = None + while curr != task: + group_node = ramdump.read_pointer(group_node) + curr = group_node - group_offset + size += get_bufs(curr, bufs, ion_info, ramdump) + return size + + +def ion_proc_info(self, ramdump, ion_info): + ion_info = ramdump.open_file('ionproc.txt') + init_task = ramdump.address_of('init_task') + if init_task is None: + ion_info.write("NOTE: 'init_task' not found for process information") + return + ion_info.write("*****Parsing dma proc info for ion leak debugging*****\n") + node_offset = ramdump.field_offset('struct task_struct', 'tasks') + list_node = ramdump.read_word(init_task + node_offset) + task = None + pid_offset = ramdump.field_offset('struct task_struct', 'tgid') + comm_offset = ramdump.field_offset('struct task_struct', 'comm') + dma_procs = [] + while (task != init_task): + list_node = ramdump.read_pointer(list_node) + task = list_node - node_offset + bufs = [] + size = get_proc_bufs(task, bufs, ion_info, ramdump) + if (size == 0): + continue + comm = ramdump.read_cstring(task + comm_offset) + pid = ramdump.read_int(task + pid_offset) + dma_procs.append([comm, pid, bytes_to_KB(size), bufs]) + + dma_procs.sort(key=lambda item: -item[2]) + for proc in dma_procs: + str = "\n{0} (PID {1}) size (KB): {2}\n"\ + .format(proc[0], proc[1], proc[2]) + ion_info.write(str) + ion_info.write("{0:15} {1:15} {2:15} {3:15}\n".format( + 'Name', 'Size', 'Size in KB', 'Time Alive(sec)')) + for item in proc[3]: + str = "{0:15} {1:15} {2:10} {3:15}\n".\ + format(item[0], item[1], item[2], item[3]) + ion_info.write(str) + + def do_dump_ionbuff_info(self, ramdump, ion_info): addressspace = 8 heap_addr_array = [] @@ -413,5 +521,6 @@ class DumpIonBuffer(RamParser): self.logger.info("Starting --print-ionbuffer") if (self.ramdump.kernel_version >= (4, 14)): ion_buffer_info(self, self.ramdump, ion_info) + ion_proc_info(self, self.ramdump, ion_info) else: do_dump_ionbuff_info(self, self.ramdump, ion_info) -- GitLab