Esempio n. 1
0
 def check_free_pages(self) -> None:
     for order in range(array_size(self.gdb_obj["free_area"])):
         area = self.gdb_obj["free_area"][order]
         self._check_free_area(area, False, order)
     for cpu in for_each_online_cpu():
         pageset = get_percpu_var(self.gdb_obj["pageset"], cpu)
         self._check_free_area(pageset["pcp"], True, cpu)
Esempio n. 2
0
    def _get_loadavg_values(self) -> List[float]:
        metrics = []
        for index in range(0, array_size(self.symvals.avenrun)):
            metrics.append(self._calculate_loadavg(
                self.symvals.avenrun[index]))

        return metrics
Esempio n. 3
0
    def task_state_flags_callback(cls, symbol):
        count = array_size(cls.task_state_array)

        bit = 0
        for i in range(count):
            state = cls.task_state_array[i].string()
            state_strings = {
                '(running)'      : 'TASK_RUNNING',
                '(sleeping)'     : 'TASK_INTERRUPTIBLE',
                '(disk sleep)'   : 'TASK_UNINTERRUPTIBLE',
                '(stopped)'      : 'TASK_STOPPED',
                '(zombie)'       : 'TASK_ZOMBIE',
                #'(dead)'        : 'TASK_DEAD',
                '(swapping)'     : 'TASK_SWAPPING',
                #'(tracing stop)' : 'TASK_TRACING_STOPPED',
                '(wakekill)'     : 'TASK_WAKEKILL',
                '(waking)'       : 'TASK_WAKING',
            }

            for key in state_strings:
                if key in state:
                    try:
                        dv = get_delayed_lookup(cls, state_strings[key])
                        dv.callback(bit)
                    except KeyError:
                        setattr(cls, state_strings[key], bit)
                if '(dead)' in state:
                    cls.TASK_DEAD = bit
                if '(tracing stop)' in state:
                    cls.TASK_TRACING_STOPPED = bit
            if bit == 0:
                bit = 1
            else:
                bit <<= 1
        cls.check_state_bits()
Esempio n. 4
0
    def task_state_flags_callback(cls, symbol):
        count = array_size(cls.task_state_array)

        bit = 0
        for i in range(count):
            state = cls.task_state_array[i].string()
            state_strings = {
                '(running)'      : 'TASK_RUNNING',
                '(sleeping)'     : 'TASK_INTERRUPTIBLE',
                '(disk sleep)'   : 'TASK_UNINTERRUPTIBLE',
                '(stopped)'      : 'TASK_STOPPED',
                '(zombie)'       : 'TASK_ZOMBIE',
                #'(dead)'        : 'TASK_DEAD',
                '(swapping)'     : 'TASK_SWAPPING',
                #'(tracing stop)' : 'TASK_TRACING_STOPPED',
                '(wakekill)'     : 'TASK_WAKEKILL',
                '(waking)'       : 'TASK_WAKING',
            }

            for key in state_strings:
                if key in state:
                    try:
                        dv = get_delayed_lookup(cls, state_strings[key])
                        dv.callback(bit)
                    except KeyError:
                        setattr(cls, state_strings[key], bit)
                if '(dead)' in state:
                    cls.TASK_DEAD = bit
                if '(tracing stop)' in state:
                    cls.TASK_TRACING_STOPPED = bit
            if bit == 0:
                bit = 1
            else:
                bit <<= 1
        cls.check_state_bits()
Esempio n. 5
0
    def _check_free_area(self, area: gdb.Value, is_pcp: bool, order_cpu: int) -> None:
        nr_free = 0
        if is_pcp:
            list_array_name = "lists"
            error_desc = "pcplist"
            order_cpu_desc = f"cpu {order_cpu}"
        else:
            list_array_name = "free_list"
            error_desc = "free area"
            order_cpu_desc = f"order {order_cpu}"
        for mt in range(array_size(area[list_array_name])):
            free_list = area[list_array_name][mt]
            for reverse in [False, True]:
                if reverse:
                    print("Retrying list in reverse direction")
                try:
                    for page_obj in list_for_each_entry(free_list,
                                                        self.types.page_type,
                                                        "lru",
                                                        reverse=reverse):
                        page = crash.types.page.Page.from_obj(page_obj)
                        if not page:
                            print(f"page 0x{int(page_obj.address):x} is not a valid page pointer on "
                                  f"{error_desc} of node {self.nid} zone {self.zid}, {order_cpu_desc} mt {mt}")
                            continue

                        nr_free += 1

                        if is_pcp:
                            errors = page.check_pcplist_page()
                        else:
                            errors = page.check_freelist_page(order_cpu)

                        if errors != "":
                            print(f"page 0x{int(page_obj.address):x} pfn {page.pfn} on {error_desc} of node "
                                  f"{self.nid} zone {self.zid}, {order_cpu_desc} mt {mt} had unexpected state: {errors}")
                        if page.get_nid() != self.nid or page.get_zid() != self.zid:
                            print(f"page 0x{int(page_obj.address):x} pfn {page.pfn} misplaced on "
                                  f"{error_desc} of node {self.nid} zone {self.zid}, {order_cpu_desc} mt {mt} "
                                  f"has flags for node {page.get_nid()} zone {page.get_zid()}")
                except CorruptListError as e:
                    print(f"Error traversing {error_desc} 0x{int(area.address):x} for {order_cpu_desc} mt {mt}: {e}")
                    continue
                except BufferError as e:
                    print(f"Error traversing {error_desc} 0x{int(area.address):x} for {order_cpu_desc} mt {mt}: {e}")
                    continue
                break
        nr_expected = area["count"] if is_pcp else area["nr_free"]
        if nr_free != nr_expected:
            print(f"nr_free mismatch in {error_desc} 0x{int(area.address):x} for {order_cpu_desc}: "
                  f"expected {nr_expected}, counted {nr_free}")
Esempio n. 6
0
    def setup_nr_cpus(cls, unused: gdb.Symbol) -> None:
        if cls._nr_cpus == 0:
            cls._nr_cpus = array_size(symvals['__per_cpu_offset'])

        if cls._last_cpu == -1:
            cls._last_cpu = cls._nr_cpus
Esempio n. 7
0
    def task_state_flags_callback(cls, symbol: gdb.Symbol) -> None:
        # pylint: disable=unused-argument
        """
        Detect which task flags this kernel uses.

        Meant to be used as a SymbolCallback.

        Different kernels use different task flags or even different values
        for the same flags.  This method tries to determine the flags for
        the kernel.

        Args:
            symbol: The ``task_state_array`` symbol.
        """
        task_state_array = symbol.value()
        count = array_size(task_state_array)

        bit = 0
        for i in range(count):
            state = task_state_array[i].string()
            state_strings = {
                '(running)'      : 'TASK_RUNNING',
                '(sleeping)'     : 'TASK_INTERRUPTIBLE',
                '(disk sleep)'   : 'TASK_UNINTERRUPTIBLE',
                '(stopped)'      : 'TASK_STOPPED',
                '(zombie)'       : 'EXIT_ZOMBIE',
                'x (dead)'       : 'TASK_DEAD',
                'X (dead)'       : 'EXIT_DEAD',
                '(swapping)'     : 'TASK_SWAPPING',
                '(tracing stop)' : 'TASK_TRACING_STOPPED',
                '(wakekill)'     : 'TASK_WAKEKILL',
                '(waking)'       : 'TASK_WAKING',
                '(parked)'       : 'TASK_PARKED',
                '(idle)'         : '__TASK_IDLE',
            }

            for key in state_strings:
                if key in state:
                    setattr(cls, state_strings[key], bit)

            if bit == 0:
                bit = 1
            else:
                bit <<= 1

        # Linux 4.14 re-introduced TASK_PARKED into task_state_array
        # which renumbered some bits
        if cls.has_flag('TASK_PARKED') and not cls.has_flag('TASK_DEAD'):
            newbits = cls.TASK_PARKED << 1
            cls.TASK_DEAD = newbits
            cls.TASK_WAKEKILL = newbits << 1
            cls.TASK_WAKING = newbits << 2
            cls.TASK_NOLOAD = newbits << 3
            cls.TASK_NEW = newbits << 4

            assert cls.TASK_PARKED == 0x0040
            assert cls.TASK_DEAD == 0x0080
            assert cls.TASK_WAKEKILL == 0x0100
            assert cls.TASK_WAKING == 0x0200

        # Linux 3.14 removed several elements from task_state_array
        # so we'll have to make some assumptions.
        # TASK_NOLOAD wasn't introduced until 4.2 and wasn't added
        # to task_state_array until v4.14.  There's no way to
        # detect whether the use of the flag is valid for a particular
        # kernel release.
        elif cls.has_flag('EXIT_DEAD'):
            if cls.EXIT_ZOMBIE > cls.EXIT_DEAD:
                newbits = cls.EXIT_ZOMBIE << 1
            else:
                newbits = cls.EXIT_DEAD << 1
            cls.TASK_DEAD = newbits
            cls.TASK_WAKEKILL = newbits << 1
            cls.TASK_WAKING = newbits << 2
            cls.TASK_PARKED = newbits << 3
            cls.TASK_NOLOAD = newbits << 4
            cls.TASK_NEW = newbits << 5

            assert cls.TASK_DEAD == 0x0040
            assert cls.TASK_WAKEKILL == 0x0080
            assert cls.TASK_WAKING == 0x0100
            assert cls.TASK_PARKED == 0x0200
        else:
            assert cls.TASK_DEAD == 64
            assert cls.TASK_WAKEKILL == 128
            assert cls.TASK_WAKING == 256
            assert cls.TASK_PARKED == 512

        if cls.has_flag('TASK_NOLOAD'):
            assert cls.TASK_NOLOAD == 1024
            cls.TASK_IDLE = cls.TASK_NOLOAD | cls.TASK_UNINTERRUPTIBLE
            assert cls.TASK_IDLE == 1026
        if cls.has_flag('TASK_NEW'):
            assert cls.TASK_NEW == 2048

        cls._check_state_bits()
Esempio n. 8
0
 def _get_rss_stat_field(self) -> int:
     stat = self.task_struct['mm']['rss_stat']['count']
     rss = 0
     for i in range(array_size(stat)):
         rss += int(stat[i]['counter'])
     return rss
Esempio n. 9
0
    def get_loadavg_values(self):
        metrics = []
        for index in range(0, array_size(self.avenrun)):
            metrics.append(self.calculate_loadavg(self.avenrun[index]))

        return metrics
Esempio n. 10
0
 def setup_nr_cpus(cls, ignored):
     cls.nr_cpus = array_size(cls.__per_cpu_offset)
     # piggyback on this as it seems those minsymbols at the time of
     # their callback yield offset of 0
     cls.setup_kaslr_offset()
Esempio n. 11
0
 def setup_nr_cpus(cls, ignored):
     cls.nr_cpus = array_size(cls.__per_cpu_offset)