def print_slab_page_info(self, ramdump, slab, slab_node, start, out_file, map_fn): page = self.ramdump.read_word(start) seen = [] if page == 0: return slab_lru_offset = self.ramdump.field_offset('struct page', 'lru') page_flags_offset = self.ramdump.field_offset('struct page', 'flags') max_pfn_addr = self.ramdump.address_of('max_pfn') max_pfn = self.ramdump.read_word(max_pfn_addr) max_page = pfn_to_page(ramdump, max_pfn) while page != start: if page is None: return if page in seen: return if page > max_page: return seen.append(page) page = page - slab_lru_offset page_flags = self.ramdump.read_word(page + page_flags_offset) page_addr = page_address(self.ramdump, page) self.print_slab(self.ramdump, page_addr, slab, page, out_file, map_fn) page = self.ramdump.read_word(page + slab_lru_offset)
def print_slab_page_info(self, ramdump, slab, slab_node, start, out_file): page = self.ramdump.read_word(start) seen = [] if page == 0: return slab_lru_offset = self.ramdump.field_offset("struct page", "lru") page_flags_offset = self.ramdump.field_offset("struct page", "flags") slab_node_offset = self.ramdump.field_offset("struct kmem_cache", "size") max_pfn_addr = self.ramdump.addr_lookup("max_pfn") max_pfn = self.ramdump.read_word(max_pfn_addr) max_page = pfn_to_page(ramdump, max_pfn) while page != start: if page is None: return if page in seen: return if page > max_page: return seen.append(page) page = page - slab_lru_offset page_flags = self.ramdump.read_word(page + page_flags_offset) page_addr = page_address(self.ramdump, page) self.print_slab(self.ramdump, page_addr, slab, page, out_file) page = self.ramdump.read_word(page + slab_lru_offset)
def parse(self): if not self.ramdump.is_config_defined('CONFIG_PAGE_OWNER'): return min_pfn_addr = self.ramdump.address_of('min_low_pfn') max_pfn_addr = self.ramdump.address_of('max_pfn') min_pfn = self.ramdump.read_word(min_pfn_addr) + ( self.ramdump.phys_offset >> 12) max_pfn = self.ramdump.read_word(max_pfn_addr) + ( self.ramdump.phys_offset >> 12) order_offset = self.ramdump.field_offset('struct page', 'order') flags_offset = self.ramdump.field_offset('struct page', 'flags') trace_offset = self.ramdump.field_offset('struct page', 'trace') nr_entries_offset = self.ramdump.field_offset('struct stack_trace', 'nr_entries') trace_entries_offset = self.ramdump.field_offset( 'struct page', 'trace_entries') out_tracking = self.ramdump.open_file('page_tracking.txt') out_frequency = self.ramdump.open_file('page_frequency.txt') sorted_pages = {} trace_entry_size = self.ramdump.sizeof("unsigned long") for pfn in range(min_pfn, max_pfn): page = pfn_to_page(self.ramdump, pfn) # validate this page is free if page_buddy(self.ramdump, page): continue nr_trace_entries = self.ramdump.read_int(page + trace_offset + nr_entries_offset) if nr_trace_entries <= 0 or nr_trace_entries > 16: continue out_tracking.write('PFN 0x{0:x} page 0x{1:x}\n'.format(pfn, page)) alloc_str = '' for i in range(0, nr_trace_entries): addr = self.ramdump.read_word(page + trace_entries_offset + i * trace_entry_size) if addr == 0: break look = self.ramdump.unwind_lookup(addr) if look is None: break symname, offset = look unwind_dat = ' [<{0:x}>] {1}+0x{2:x}\n'.format( addr, symname, offset) out_tracking.write(unwind_dat) alloc_str = alloc_str + unwind_dat if alloc_str in sorted_pages: sorted_pages[alloc_str] = sorted_pages[alloc_str] + 1 else: sorted_pages[alloc_str] = 1 out_tracking.write('\n') sortlist = sorted(sorted_pages.iteritems(), key=lambda (k, v): (v), reverse=True) for k, v in sortlist: out_frequency.write('Allocated {0} times\n'.format(v)) out_frequency.write(k) out_frequency.write('\n') out_tracking.close() out_frequency.close() print_out_str( '---wrote page tracking information to page_tracking.txt') print_out_str( '---wrote page frequency information to page_frequency.txt')
def parse(self): if not self.ramdump.is_config_defined('CONFIG_DEBUG_PAGEALLOC'): print_out_str('CONFIG_DEBUG_PAGEALLOC Not enabled') return out_corruption_summary = self.ramdump.open_file( 'page_corruption_summary.txt') out_pfn_ranges = self.ramdump.open_file('page_ranges.txt') memblock_addr = self.ramdump.address_of('memblock') memblock_memory_offset = self.ramdump.field_offset( 'struct memblock', 'memory') memblock_memory_cnt_offset = self.ramdump.field_offset( 'struct memblock_type', 'cnt') cnt = self.ramdump.read_word(memblock_addr + memblock_memory_offset + memblock_memory_cnt_offset) region_offset = self.ramdump.field_offset('struct memblock_type', 'regions') regions_baseaddr = self.ramdump.read_word(memblock_addr + memblock_memory_offset + region_offset) page_ext_offset = self.ramdump.field_offset('struct mem_section', 'page_ext') page_flags_offset = self.ramdump.field_offset('struct page_ext', 'flags') mem_section_size = self.ramdump.sizeof("struct mem_section") mem_section = self.ramdump.read_word('mem_section') page_ext_size = self.ramdump.sizeof("struct page_ext") for r in range(0, cnt): region_addr = regions_baseaddr + r * self.ramdump.sizeof( 'struct memblock_region') start_addr_offset = self.ramdump.field_offset( 'struct memblock_region', 'base') start_addr = self.ramdump.read_u32(region_addr + start_addr_offset) size_offset = self.ramdump.field_offset('struct memblock_region', 'size') region_size = self.ramdump.read_u32(region_addr + size_offset) end_addr = start_addr + region_size min_pfn = start_addr >> 12 max_pfn = end_addr >> 12 out_pfn_ranges.write("min_pfn : %s,max_pfn: %s\n" % (hex(min_pfn), hex(max_pfn))) for pfn in range(min_pfn, max_pfn): page = pfn_to_page(self.ramdump, pfn) page_pa = (pfn << 12) if (self.ramdump.kernel_version > (3, 18, 0)): free = 0 offset = page_pa >> 30 mem_section_0_offset = (mem_section + (offset * mem_section_size)) page_ext = self.ramdump.read_word(mem_section_0_offset + page_ext_offset) temp_page_ext = page_ext + (pfn * page_ext_size) page_ext_flags = self.ramdump.read_word(temp_page_ext + page_flags_offset) # enum PAGE_EXT_DEBUG_POISON ( == 0th bit is set ) for page poisioning free = page_ext_flags & 1 else: # debug_flags value should be 1 for pages having poisoned value 0xaa free = get_debug_flags(self.ramdump, page) if free == 1: flag = 0 for i in range(0, 1024): readval = self.ramdump.read_u32(page_pa + i * 4, False) if readval == None: break if readval != 0xaaaaaaaa: flag = 1 diff = 0xaaaaaaaa - readval if diff < 0: diff = diff * (-1) isBitFlip = not (diff & diff - 1) if isBitFlip: out_corruption_summary.write( "Single Bit Error at %s" % ("%#0.8x" % (page_pa + i * 4))) out_corruption_summary.write("\n") else: out_corruption_summary.write( "Corruption at %s" % ("%#0.8x" % (page_pa + i * 4))) out_corruption_summary.write("\n") end_addr = page_pa + i * 4 + 0x00000100 end_page_addr = page_pa | 0x00000fff if end_addr > end_page_addr: end_addr = end_page_addr count = 0 for wordaddr in range(page_pa + i * 4, end_addr, 0x00000004): if count == 0: out_corruption_summary.write( "%s " % ("%#0.8x" % (wordaddr))) readval = self.ramdump.read_u32( wordaddr, False) out_corruption_summary.write( "%s " % ("%#0.8x" % (readval))) count = count + 1 if count == 8: count = 0 out_corruption_summary.write("\n") break if flag == 1: out_corruption_summary.write("\n") out_corruption_summary.close() out_pfn_ranges.close()
def parse(self): ramdump = self.ramdump if not ramdump.is_config_defined('CONFIG_PAGE_OWNER'): return cmdline = ramdump.get_command_line() if cmdline.find("page_owner=on") == -1: return pageflags_table = ramdump.gdbmi.get_enum_lookup_table('pageflags', 26) self.pageflags[pageflags_table.index("PG_slab")] = 'S' self.pageflags[pageflags_table.index("PG_lru")] = 'L' page_ext_flags_table = ramdump.gdbmi.get_enum_lookup_table( 'page_ext_flags', 5) PAGE_EXT_OWNER = (1 << page_ext_flags_table.index('PAGE_EXT_OWNER')) page_ext_obj = mm_page_ext(ramdump) meminfo.gen_symbol_info(ramdump.nm_path, ramdump.vmlinux) min_pfn = page_ext_obj.get_min_pfn() max_pfn = page_ext_obj.get_max_pfn() page_flags_offset = ramdump.field_offset('struct page', 'flags') order_offset = ramdump.field_offset('struct page_ext', 'order') page_ext_flags_offset = ramdump.field_offset('struct page_ext', 'flags') nr_entries_offset = ramdump.field_offset('struct page_ext', 'nr_entries') trace_entries_offset = ramdump.field_offset('struct page_ext', 'trace_entries') trace_entry_size = ramdump.sizeof("void *") out_tracking = ramdump.open_file('page_tracking.txt') out_tracking_all = ramdump.open_file('page_tracking_all.txt') page_info = meminfo.meminfo_ranked(self.ramdump) pfn = min_pfn while pfn < max_pfn: order = 0 trace_entries = [] page_ext = page_ext_obj.lookup_page_ext(pfn) page_ext_flags = ramdump.read_word(page_ext + page_ext_flags_offset) if ((page_ext_flags & PAGE_EXT_OWNER) == PAGE_EXT_OWNER): page = pfn_to_page(ramdump, pfn) page_flags = ramdump.read_u32(page + page_flags_offset) order = ramdump.read_u32(page_ext + order_offset) nr_trace_entries = ramdump.read_int(page_ext + nr_entries_offset) flags = self.get_flags_str(page_flags) size = order_to_size(order) for i in range(0, nr_trace_entries): entry = ramdump.read_word(page_ext + trace_entries_offset + i * trace_entry_size) trace_entries.append(entry) page_info.insert([], range(pfn, pfn + (1 << order)), trace_entries, size, flags) pfn += (1 << order) alloc_size = 0 dma_size = 0 network_dma_size = 0 wifi_dma_size = 0 nss_dma_size = 0 direct_page_alloc_size = 0 network_direct_page_alloc_size = 0 wifi_direct_page_alloc_size = 0 nss_direct_page_alloc_size = 0 slub_alloc_size = 0 other_alloc_size = 0 kernel_used_size = 0 sorted_meminfo = page_info.sort_by_size() for info in sorted_meminfo: m = sorted_meminfo[info] out_tracking_all.write(m.obj_in_str(True)) if m.allocation_type == "Fallback": kernel_used_size += m.total_size continue if m.allocation_type == "IO Remapped Allocation": alloc_size += m.total_size continue alloc_size += m.total_size if m.flags == "" and m.allocation_type == "DMA Allocation": dma_size += m.total_size if m.category == "Networking": if m.subcategory == "WiFi": wifi_dma_size += m.total_size if m.subcategory == "NSS": nss_dma_size += m.total_size elif m.allocation_type == "Alloc Pages allocation": direct_page_alloc_size += m.total_size if m.category == "Networking": if m.subcategory == "WiFi": wifi_direct_page_alloc_size += m.total_size if m.subcategory == "NSS": nss_direct_page_alloc_size += m.total_size if m.flags.find("S") >= 0: slub_alloc_size += m.total_size out_tracking.write(str(m)) network_dma_size = wifi_dma_size + nss_dma_size network_direct_page_alloc_size = (wifi_direct_page_alloc_size + nss_direct_page_alloc_size) other_alloc_size = alloc_size - (dma_size + direct_page_alloc_size + slub_alloc_size) out_tracking_all.close() out_tracking.close() print_out_str("Total pages allocated: {0} KB".format(alloc_size / 1024)) print_out_str("\tTotal DMA allocation: {0} KB".format(dma_size / 1024)) print_out_str("\t\tNetwork DMA allocation: {0} KB".format( network_dma_size / 1024)) print_out_str("\t\t\tWiFi DMA allocation: {0} KB".format( wifi_dma_size / 1024)) print_out_str("\t\t\tNSS DMA allocation: {0} KB".format(nss_dma_size / 1024)) print_out_str("\tDirect page allocation: {0} KB".format( direct_page_alloc_size / 1024)) print_out_str("\t\tNetwork direct page allocation: {0} KB".format( network_direct_page_alloc_size / 1024)) print_out_str("\t\t\tWiFi direct page allocation: {0} KB".format( wifi_direct_page_alloc_size / 1024)) print_out_str("\t\t\tNSS direct page allocation: {0} KB".format( nss_direct_page_alloc_size / 1024)) print_out_str("\tTotal SLUB allocation: {0} KB".format( slub_alloc_size / 1024)) print_out_str("\tOther allocation: {0} KB".format(other_alloc_size / 1024)) print_out_str("Kernel private: {0} KB\n".format(kernel_used_size / 1024)) print_out_str( '---wrote page tracking information to page_tracking.txt')
def parse(self): if not self.ramdump.is_config_defined("CONFIG_PAGE_OWNER"): return min_pfn_addr = self.ramdump.address_of("min_low_pfn") max_pfn_addr = self.ramdump.address_of("max_pfn") min_pfn = self.ramdump.read_word(min_pfn_addr) + (self.ramdump.phys_offset >> 12) max_pfn = self.ramdump.read_word(max_pfn_addr) + (self.ramdump.phys_offset >> 12) order_offset = self.ramdump.field_offset("struct page", "order") flags_offset = self.ramdump.field_offset("struct page", "flags") trace_offset = self.ramdump.field_offset("struct page", "trace") nr_entries_offset = self.ramdump.field_offset("struct stack_trace", "nr_entries") trace_entries_offset = self.ramdump.field_offset("struct page", "trace_entries") out_tracking = self.ramdump.open_file("page_tracking.txt") out_frequency = self.ramdump.open_file("page_frequency.txt") sorted_pages = {} trace_entry_size = self.ramdump.sizeof("unsigned long") for pfn in range(min_pfn, max_pfn): page = pfn_to_page(self.ramdump, pfn) # validate this page is free if page_buddy(self.ramdump, page): continue nr_trace_entries = self.ramdump.read_int(page + trace_offset + nr_entries_offset) if nr_trace_entries <= 0 or nr_trace_entries > 16: continue out_tracking.write("PFN 0x{0:x} page 0x{1:x}\n".format(pfn, page)) alloc_str = "" for i in range(0, nr_trace_entries): addr = self.ramdump.read_word(page + trace_entries_offset + i * trace_entry_size) if addr == 0: break look = self.ramdump.unwind_lookup(addr) if look is None: break symname, offset = look unwind_dat = " [<{0:x}>] {1}+0x{2:x}\n".format(addr, symname, offset) out_tracking.write(unwind_dat) alloc_str = alloc_str + unwind_dat if alloc_str in sorted_pages: sorted_pages[alloc_str] = sorted_pages[alloc_str] + 1 else: sorted_pages[alloc_str] = 1 out_tracking.write("\n") sortlist = sorted(sorted_pages.iteritems(), key=lambda (k, v): (v), reverse=True) for k, v in sortlist: out_frequency.write("Allocated {0} times\n".format(v)) out_frequency.write(k) out_frequency.write("\n") out_tracking.close() out_frequency.close() print_out_str("---wrote page tracking information to page_tracking.txt") print_out_str("---wrote page frequency information to page_frequency.txt")
def print_slab_summary(self, slab_out): total_freeobjects = 0 original_slab = self.ramdump.addr_lookup('slab_caches') cpu_present_bits_addr = self.ramdump.addr_lookup('cpu_present_bits') cpu_present_bits = self.ramdump.read_word(cpu_present_bits_addr) cpus = bin(cpu_present_bits).count('1') slab_list_offset = self.ramdump.field_offset( 'struct kmem_cache', 'list') slab_name_offset = self.ramdump.field_offset( 'struct kmem_cache', 'name') slab_node_offset = self.ramdump.field_offset( 'struct kmem_cache', 'node') cpu_cache_page_offset = self.ramdump.field_offset( 'struct kmem_cache_cpu', 'page') cpu_slab_offset = self.ramdump.field_offset( 'struct kmem_cache', 'cpu_slab') slab_partial_offset = self.ramdump.field_offset( 'struct kmem_cache_node', 'partial') slab = self.ramdump.read_word(original_slab) slab_lru_offset = self.ramdump.field_offset( 'struct page', 'lru') max_pfn_addr = self.ramdump.addr_lookup('max_pfn') max_pfn = self.ramdump.read_word(max_pfn_addr) max_page = pfn_to_page(self.ramdump, max_pfn) format_string = '\n{0:35} {1:9} {2:10} {3:10} {4:8}K {5:10} {6:10}K' slab_out.write( '{0:35} {1:9} {2:10} {3:10} {4:8} {5:10} {6:10}'.format( "NAME", "OBJSIZE", "ALLOCATED", "TOTAL", "TOTAL*SIZE", "SLABS", "SSIZE")) while slab != original_slab: total_freeobjects = 0 slab = slab - slab_list_offset slab_name_addr = self.ramdump.read_word( slab + slab_name_offset) # actually an array but again, no numa slab_node_addr = self.ramdump.read_word( slab + slab_node_offset) slab_name = self.ramdump.read_cstring( slab_name_addr, 48) cpu_slab_addr = self.ramdump.read_word( slab + cpu_slab_offset) oo = self.ramdump.read_structure_field( slab, 'struct kmem_cache', 'oo') obj_size = self.ramdump.read_structure_field( slab, 'struct kmem_cache', 'object_size') objsize_w_metadata = self.ramdump.read_structure_field( slab, 'struct kmem_cache', 'size') nr_total_objects = self.ramdump.read_structure_field( slab_node_addr, 'struct kmem_cache_node', 'total_objects') num_slabs = self.ramdump.read_structure_field( slab_node_addr, 'struct kmem_cache_node', 'nr_slabs') # per cpu slab for i in range(0, cpus): cpu_slabn_addr = self.ramdump.read_word( cpu_slab_addr, cpu=i) if cpu_slabn_addr == 0 or None: break total_freeobjects = total_freeobjects + self.cal_free_pages( self.ramdump, (cpu_slabn_addr + cpu_cache_page_offset), slab_lru_offset, max_page) total_freeobjects = total_freeobjects + self.cal_free_pages( self.ramdump, slab_node_addr + slab_partial_offset, slab_lru_offset, max_page) total_allocated = nr_total_objects - total_freeobjects page_order = oo >> OO_SHIFT slab_size = int(math.pow(2, page_order + PAGE_SHIFT)) slab_size = slab_size / 1024 slab = self.ramdump.read_word(slab + slab_list_offset) slab_out.write(format_string.format( slab_name, obj_size, total_allocated, nr_total_objects, (objsize_w_metadata * nr_total_objects)/1024, num_slabs, slab_size))
def parse(self): if not self.ramdump.is_config_defined('CONFIG_PAGE_OWNER'): print_out_str('CONFIG_PAGE_OWNER not defined') return if (self.ramdump.kernel_version >= (3, 19, 0)): if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): mem_section = self.ramdump.read_word('mem_section') if self.ramdump.kernel_version >= (4, 14): mem_section = self.ramdump.read_word(mem_section) else: mem_section = self.ramdump.address_of('contig_page_data') trace_offset = 0 nr_entries_offset = 0 trace_entries_offset = 0 offset = 0 struct_holding_trace_entries = 0 trace_entry_size = self.ramdump.sizeof("unsigned long") if (self.ramdump.kernel_version <= (3, 19, 0)): trace_offset = self.ramdump.field_offset('struct page', 'trace') nr_entries_offset = self.ramdump.field_offset( 'struct stack_trace', 'nr_entries') trace_entries_offset = self.ramdump.field_offset( 'struct page', 'trace_entries') else: if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): page_ext_offset = self.ramdump.field_offset( 'struct mem_section', 'page_ext') else: page_ext_offset = self.ramdump.field_offset( 'struct pglist_data', 'node_page_ext') trace_offset = self.ramdump.field_offset('struct page_ext', 'trace') if self.ramdump.is_config_defined('CONFIG_STACKDEPOT'): trace_entries_offset = self.ramdump.field_offset( 'struct stack_record', 'entries') else: trace_entries_offset = self.ramdump.field_offset( 'struct page_ext', 'trace_entries') nr_entries_offset = self.ramdump.field_offset( 'struct page_ext', 'nr_entries') if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): mem_section_size = self.ramdump.sizeof("struct mem_section") else: mem_section_size = 0 page_ext_size = self.ramdump.sizeof("struct page_ext") if self.ramdump.kernel_version >= (4, 9, 0): page_owner_size = self.ramdump.sizeof("struct page_owner") page_ext_size = page_ext_size + page_owner_size page_owner_ops_offset = self.ramdump.read_structure_field( 'page_owner_ops', 'struct page_ext_operations', 'offset') out_tracking = self.ramdump.open_file('page_tracking.txt') out_frequency = self.ramdump.open_file('page_frequency.txt') sorted_pages = {} ''' Following based upon definition in include/linux/mmzone.h #ifndef CONFIG_FORCE_MAX_ZONEORDER #define MAX_ORDER 11 #else #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER #endif ''' try: max_order = int( self.ramdump.get_config_val("CONFIG_FORCE_MAX_ZONEORDER")) except: max_order = 11 for pfn in for_each_pfn(self.ramdump): page = pfn_to_page(self.ramdump, pfn) order = 0 """must be allocated, and the first pfn of an order > 0 page""" if (page_buddy(self.ramdump, page) or page_count(self.ramdump, page) == 0): continue if (self.ramdump.kernel_version <= (3, 19, 0)): nr_trace_entries = self.ramdump.read_int(page + trace_offset + nr_entries_offset) struct_holding_trace_entries = page order = self.ramdump.read_structure_field( page, 'struct page', 'order') else: phys = pfn << 12 if phys is None or phys is 0: continue offset = phys >> 30 if self.ramdump.is_config_defined('CONFIG_SPARSEMEM'): mem_section_0_offset = (mem_section + (offset * mem_section_size)) page_ext = self.ramdump.read_word(mem_section_0_offset + page_ext_offset) else: page_ext = self.ramdump.read_word(mem_section + page_ext_offset) if self.ramdump.arm64: temp_page_ext = page_ext + (pfn * page_ext_size) else: pfn_index = pfn - (self.ramdump.phys_offset >> 12) temp_page_ext = page_ext + (pfn_index * page_ext_size) if self.ramdump.kernel_version >= (4, 9, 0): temp_page_ext = temp_page_ext + page_owner_ops_offset order = self.ramdump.read_structure_field( temp_page_ext, 'struct page_owner', 'order') else: order = self.ramdump.read_structure_field( temp_page_ext, 'struct page_ext', 'order') if not self.ramdump.is_config_defined('CONFIG_STACKDEPOT'): nr_trace_entries = self.ramdump.read_int(temp_page_ext + nr_entries_offset) struct_holding_trace_entries = temp_page_ext else: if self.ramdump.kernel_version >= (4, 9, 0): handle = self.ramdump.read_structure_field( temp_page_ext, 'struct page_owner', 'handle') else: handle = self.ramdump.read_structure_field( temp_page_ext, 'struct page_ext', 'handle') slabindex = handle & 0x1fffff handle_offset = (handle >> 0x15) & 0x3ff handle_offset = handle_offset << 4 stack_slabs = self.ramdump.address_of('stack_slabs') stack_slabs_size = self.ramdump.sizeof('void *') slab = self.ramdump.read_word(stack_slabs + (stack_slabs_size * slabindex)) stack = slab + handle_offset nr_trace_entries = self.ramdump.read_structure_field( stack, 'struct stack_record', 'size') struct_holding_trace_entries = stack if nr_trace_entries <= 0 or nr_trace_entries > 16: continue if order >= max_order: out_tracking.write( 'PFN 0x{:x} page 0x{:x} skip as order 0x{:x}\n'.format( pfn, page, order)) continue out_tracking.write('PFN 0x{:x}-0x{:x} page 0x{:x}\n'.format( pfn, pfn + (1 << order) - 1, page)) alloc_str = '' for i in range(0, nr_trace_entries): addr = self.ramdump.read_word(struct_holding_trace_entries + trace_entries_offset + i * trace_entry_size) if addr == 0: break look = self.ramdump.unwind_lookup(addr) if look is None: break symname, offset = look unwind_dat = ' [<{0:x}>] {1}+0x{2:x}\n'.format( addr, symname, offset) out_tracking.write(unwind_dat) alloc_str = alloc_str + unwind_dat if alloc_str in sorted_pages: sorted_pages[alloc_str] = sorted_pages[alloc_str] + 1 else: sorted_pages[alloc_str] = 1 out_tracking.write('\n') sortlist = sorted(sorted_pages.iteritems(), key=lambda (k, v): (v), reverse=True) for k, v in sortlist: out_frequency.write('Allocated {0} times\n'.format(v)) out_frequency.write(k) out_frequency.write('\n') out_tracking.close() out_frequency.close() print_out_str( '---wrote page tracking information to page_tracking.txt') print_out_str( '---wrote page frequency information to page_frequency.txt')
def parse(self): if not self.ramdump.is_config_defined('CONFIG_DEBUG_PAGEALLOC'): print_out_str('CONFIG_DEBUG_PAGEALLOC Not enabled') return out_corruption_summary = self.ramdump.open_file('page_corruption_summary.txt') out_pfn_ranges = self.ramdump.open_file('page_ranges.txt') memblock_addr = self.ramdump.address_of('memblock') memblock_memory_offset = self.ramdump.field_offset('struct memblock', 'memory') memblock_memory_cnt_offset = self.ramdump.field_offset('struct memblock_type', 'cnt') cnt = self.ramdump.read_word(memblock_addr + memblock_memory_offset + memblock_memory_cnt_offset) region_offset = self.ramdump.field_offset('struct memblock_type', 'regions') regions_baseaddr = self.ramdump.read_word(memblock_addr + memblock_memory_offset + region_offset) for r in range(0,cnt) : region_addr = regions_baseaddr + r * self.ramdump.sizeof('struct memblock_region') start_addr_offset = self.ramdump.field_offset('struct memblock_region', 'base') start_addr = self.ramdump.read_u32(region_addr + start_addr_offset) size_offset = self.ramdump.field_offset('struct memblock_region', 'size') region_size = self.ramdump.read_u32(region_addr + size_offset) end_addr = start_addr + region_size min_pfn = start_addr >> 12 max_pfn = end_addr >> 12 out_pfn_ranges.write("min_pfn : %s,max_pfn: %s\n" %(hex(min_pfn),hex(max_pfn))) for pfn in range(min_pfn, max_pfn): page = pfn_to_page(self.ramdump, pfn) page_pa = (pfn << 12) # debug_flags value should be 1 for pages having poisoned value 0xaa free = get_debug_flags(self.ramdump, page) if free == 1: page_pa = (pfn << 12) flag = 0; for i in range(0,1024): readval = self.ramdump.read_u32(page_pa+i*4, False) if readval == None: break if readval!=0xaaaaaaaa: flag = 1 diff = 0xaaaaaaaa-readval if diff < 0: diff = diff * (-1) isBitFlip = not (diff & diff-1) if isBitFlip: out_corruption_summary.write("Single Bit Error at %s" %("%#0.8x"%(page_pa+i*4))) out_corruption_summary.write("\n") else: out_corruption_summary.write("Corruption at %s" %("%#0.8x"%(page_pa+i*4))) out_corruption_summary.write("\n") end_addr = page_pa + i*4 + 0x00000100 end_page_addr = page_pa | 0x00000fff if end_addr > end_page_addr: end_addr = end_page_addr count = 0 for wordaddr in range(page_pa + i*4,end_addr,0x00000004): if count == 0: out_corruption_summary.write("%s " %("%#0.8x"%(wordaddr))) readval = self.ramdump.read_u32(wordaddr, False) out_corruption_summary.write("%s " %("%#0.8x"%(readval))) count = count+1 if count == 8: count = 0 out_corruption_summary.write ("\n"); break if flag == 1 : out_corruption_summary.write("\n") out_corruption_summary.close() out_pfn_ranges.close()