diff --git a/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py b/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py index 47972f19d397e5c2582afa6ff356bb0bec1c7806..851efebf63da5426bf9f781c24d1c5d6a1f32af2 100644 --- a/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py +++ b/linux-ramdump-parser-v2/parsers/ion_buffer_parse.py @@ -1,5 +1,5 @@ """ -Copyright (c) 2016, The Linux Foundation. All rights reserved. +Copyright (c) 2016, 2018 The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -28,6 +28,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ from parser_util import register_parser, RamParser +from rb_tree import RbTree +import logging +import os RB_PARENT_COLOR_MASK = 0xFFFFFFFFFFFFFFFC grand_total = 0 @@ -112,13 +115,12 @@ def parse_heap(self, ramdump, heap_addr, ion_info): ion_dev = ramdump.read_structure_field( ion_heap, 'struct ion_heap', 'dev') - ion_dev_rb_root = ramdump.read_structure_field( - ion_dev, 'struct ion_device', 'clients') + clients_rb_root = ion_dev + ramdump.field_offset('struct ion_device', 'clients') if ionheap_total_allocated != 0: nr_clients = show_ion_dev_client( self, ramdump, - ion_dev_rb_root, + clients_rb_root, ionheap_id, ion_info) str = "\n \nTotal number of clients: {0:1}" @@ -142,11 +144,9 @@ def parse_heap(self, ramdump, heap_addr, ion_info): def parse_orphan_buffers(self, ramdump, ion_dev, heap_id, ion_info): orphan_buffer_size = 0 total_buffer_size = 0 - ion_dev_buffer_rb_root = ramdump.read_structure_field( - ion_dev, 'struct ion_device', 'buffers') - rb_node = parser( - self, 1, ramdump, ion_dev_buffer_rb_root, ion_info) + rbtree = RbTree(ramdump, ion_dev + ramdump.field_offset('struct ion_device', 'buffers'), + logger = self.logger, debug = True) ion_buffer_rb_node_offset = ramdump.field_offset( 'struct ion_buffer', 'node') @@ -156,7 +156,7 @@ def parse_orphan_buffers(self, ramdump, ion_dev, heap_id, ion_info): 'struct ion_buffer', 'ref') str = "\n buffer: 0x{0:x}, Buffer size: {1} KB " str = str + "comm: {2} PID: {3} kmap count: {4} ref_count : {5}" - while rb_node != 0: + for rb_node in rbtree: ion_buffer = rb_node - ion_buffer_rb_node_offset ion_buffer_ref_add = ion_buffer + ion_buffer_ref_offset ion_buffer_heap = ramdump.read_structure_field( @@ -188,19 +188,20 @@ def parse_orphan_buffers(self, ramdump, ion_dev, heap_id, ion_info): ion_buffer_kmap_count, ref_counter)) orphan_buffer_size = orphan_buffer_size + ion_buffer_size - rb_node = parser(self, 2, ramdump, rb_node, ion_info) return orphan_buffer_size, total_buffer_size def show_ion_dev_client( self, ramdump, - ion_dev_rb_root, + rb_root, ionheap_id, ion_info): global ion_heap_buffers nr_clients = 0 client_name = 0 - rb_node = parser(self, 1, ramdump, ion_dev_rb_root, ion_info) + + rbtree = RbTree(ramdump, rb_root, logger = self.logger, debug = True) + ion_client_node_offset = ramdump.field_offset( 'struct ion_client', 'node') task_comm_offset = ramdump.field_offset( @@ -208,8 +209,8 @@ def show_ion_dev_client( tempstr = "\n\n CLIENT: (struct ion_client *)0x{0:x} , " str = tempstr + "task : {1} / ion_client : {2} / PID: {3} / Size : {4} KB" str1 = tempstr + "ion_client : {1} / PID: {2} / Size : {3} KB" - if rb_node != 0: - while rb_node != 0: + if True: + for rb_node in rbtree: ion_client = rb_node - ion_client_node_offset heap_size = traverse_ion_heap_buffer( self, @@ -244,7 +245,6 @@ def show_ion_dev_client( client_PID, bytes_to_KB(heap_size))) for heap_buffer in ion_heap_buffers: ion_info.write(heap_buffer) - rb_node = parser(self, 2, ramdump, rb_node, ion_info) return nr_clients @@ -256,9 +256,11 @@ def traverse_ion_heap_buffer(self, ramdump, ion_client, ionheap_id, ion_info): ion_buffer_heap_size = 0 ion_heap_buffers = [] str = "\n (+) ion_buffer: 0x{0:x} size: {1:0} KB Handle Count: {2:0}" - ion_handle_rb_node = parser( - self, 1, ramdump, ion_handle_root_address, ion_info) - while ion_handle_rb_node != 0: + + rbtree = RbTree(ramdump, ion_handle_root_address, + logger=self.logger, debug = True) + + for ion_handle_rb_node in rbtree: ion_handle = ion_handle_rb_node - self.ion_handle_node_offset ion_buffer = ramdump.read_structure_field( ion_handle, 'struct ion_handle', 'buffer') @@ -278,8 +280,6 @@ def traverse_ion_heap_buffer(self, ramdump, ion_client, ionheap_id, ion_info): bytes_to_KB(ion_buffer_size), ion_buffer_handlecount) ion_heap_buffers.append(temp) - ion_handle_rb_node = parser( - self, 2, ramdump, ion_handle_rb_node, ion_info) return ion_buffer_heap_size @@ -368,4 +368,10 @@ class DumpIonBuffer(RamParser): {1}'.format(self.ramdump.kernel_version[0], self.ramdump.kernel_version[1])) return + + self.logger = logging.getLogger(__name__) + path = os.path.join(self.ramdump.outdir, 'print-ionbuffer.stderr') + self.logger.addHandler(logging.FileHandler(path, mode='w')) + self.logger.setLevel(logging.INFO) + self.logger.info("Starting --print-ionbuffer") do_dump_ionbuff_info(self, self.ramdump, ion_info) diff --git a/linux-ramdump-parser-v2/rb_tree.py b/linux-ramdump-parser-v2/rb_tree.py index 0eacfd08588a1afea2cef13a572fc1352fd5f628..dbace5e5f4296fcc9aa873ddec8bde8a10346c32 100644 --- a/linux-ramdump-parser-v2/rb_tree.py +++ b/linux-ramdump-parser-v2/rb_tree.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012-2014, The Linux Foundation. All rights reserved. +# Copyright (c) 2012-2014, 2018 The Linux Foundation. All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 and @@ -9,6 +9,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. +from print_out import print_out_str +import pdb + """ struct rb_node { @@ -20,6 +23,137 @@ struct rb_node } __attribute__((aligned(sizeof(long)))); """ +class RbTree(object): + + def __init__(self, ramdump, root, + logger = None, debug = False): + self.rd = ramdump + self.rb_root = root + + if not logger: + self.logger = logging.getLogger(__name__) + else: + self.logger = logger + self.debug = debug + + def __rb_parent(self, node): + parent_color = self.rd.read_structure_field( + node, 'struct rb_node', '__rb_parent_color') + if parent_color is None: + pdb.set_trace() + self.logger.error("struct rb_node@0x{:x}: Memory access failed".format(node)) + return 0x0 + + return parent_color & ~3 + + def __rb_left(self, node): + child = self.rd.read_structure_field(node, 'struct rb_node', 'rb_left') + if child is None: + pdb.set_trace() + self.logger.error("struct rb_node@0x{:x}: Memory access failed".format(node)) + return 0x0 + + return child + + def __rb_right(self, node): + child = self.rd.read_structure_field(node, 'struct rb_node', 'rb_right') + if child is None: + pdb.set_trace() + self.logger.error("struct rb_node@0x{:x}: Memory access failed".format(node)) + return 0x0 + + return child + + def validate(self, parent, child): + if not self.debug: + return True + + if not parent or not child: + return True + + _parent = self.__rb_parent(child) + if parent != _parent: + self.logger.error( + "Bad rb_tree child->parent pointer:\n"+ + "Parent: 0x{:x}\n".format(parent)+ + "Child: 0x{:x}\n".format(child)) + return False + + right = self.__rb_right(parent) + left = self.__rb_left(parent) + if (child != left and child != right): + self.logger.error( + "Bad rb_tree parent->child pointer:\n"+ + "Parent: 0x{:x}\n".format(parent)+ + "Child: 0x{:x}\n".format(child)) + return False + + return True + + + def rb_parent(self, node): + parent = self.__rb_parent(node) + if self.validate(parent, node): + return parent + + def rb_left(self, node): + child = self.__rb_left(node) + if self.validate(node, child): + return child + + def rb_right(self, node): + child = self.__rb_right(node) + if self.validate(node, child): + return child + + def rb_first(self, node): + if not node: + return 0x0 + + while node: + prev = node + node = self.rb_left(node) + + return prev + + def rb_next(self, node): + if not node: + return 0x0 + + right = self.rb_right(node) + if right: + return self.rb_first(right) + + while True: + parent = self.rb_parent(node) + if not parent: + return 0x0 + + right = self.rb_right(parent) + if node != right: + return parent + + node = parent + + def __iter__(self): + return self.RbTreeIter(self) + + class RbTreeIter(object): + def __init__(self, rbtree): + #pdb.set_trace() + self.rbtree = rbtree + node = rbtree.rd.read_structure_field( + rbtree.rb_root, 'struct rb_root', 'rb_node') + self.cur = rbtree.rb_first(node) + + def next(self): + if not self.cur: + raise StopIteration + self.cur = self.rbtree.rb_next(self.cur) + if not self.cur: + raise StopIteration + return self.cur + class RbTreeWalker(object):