Esempio n. 1
0
 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)
Esempio n. 2
0
 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)
Esempio n. 3
0
 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)
Esempio n. 4
0
    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()
Esempio n. 6
0
    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")
Esempio n. 8
0
    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))
Esempio n. 9
0
    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()