Example #1
0
def setup_slab_caches(slab_caches: gdb.Symbol) -> None:
    list_caches = slab_caches.value()

    for cache in list_for_each_entry(list_caches, types.kmem_cache_type,
                                     KmemCache.head_name):
        name = cache["name"].string()
        kmem_cache = KmemCache(name, cache)

        kmem_caches[name] = kmem_cache
        kmem_caches_by_addr[int(cache.address)] = kmem_cache
Example #2
0
    def setup_xen_m2p(cls, symbol: gdb.Symbol) -> None:
        xen_domain_type = int(symbol.value())
        # XXX: this is quite lazy...
        if xen_domain_type == 0:
            return

        cls.machine_to_phys_nr = int(get_symbol_value("machine_to_phys_nr"))
        cls.xen_max_p2m_pfn = int(get_symbol_value("xen_max_p2m_pfn"))
        cls.xen_p2m_addr = get_symbol_value("xen_p2m_addr")

        cls.xen_m2p_needed = True
Example #3
0
    def check_task_interface(cls, init_task: gdb.Symbol) -> None:
        """
        Check which interface to iterating over mount structures is in use

        Meant to be used as a SymbolCallback.

        Args:
            init_task: The ``init_task`` symbol.
        """
        cls._init_fs_root = init_task.value()['fs']['root']
        if struct_has_member(init_task, 'nsproxy'):
            cls._for_each_mount = cls._for_each_mount_nsproxy
        else:
            raise NotImplementedError("Mount.for_each_mount is unhandled on this kernel version")
Example #4
0
    def setup_possible_mask(cls, cpu_mask: gdb.Symbol) -> None:
        """
        Translate the ``cpu_possible_mask`` bitmap into a list of
        possible CPU numbers.

        Meant to be used as a SymbolCallback.

        Args:
            cpu_mask: The symbol for ``cpu_possible_mask`` or
                ``__cpu_possible_mask``, depending on kernel version.
        """
        cls._cpu_possible_mask = cpu_mask.value()
        bits = cls._cpu_possible_mask["bits"]
        cls.cpus_possible = list(for_each_set_bit(bits))
Example #5
0
def _setup_flag_names(symbol: gdb.Symbol) -> None:
    global gfpflag_names, pageflag_names

    flag_names = list()
    array = symbol.value()
    i = 0
    val = array[0]
    while val["mask"] != 0 and val["name"] != 0:
        flag_names.append((int(val["mask"]), str(val["name"].string())))
        i += 1
        val = array[i]
    if symbol.name == "gfpflag_names":
        gfpflag_names = flag_names
    elif symbol.name == "pageflag_names":
        pageflag_names = flag_names
    else:
        raise RuntimeError("unknown symbol passed")
Example #6
0
    def setup_node_states(cls, node_states_sym: gdb.Symbol) -> None:
        """
        Detect names of node states and which nodes are possible
        and online.

        Meant to be used as a SymbolCallback.

        Args:
            node_states_sym: The ``node_states`` symbol.
        """

        node_states = node_states_sym.value()
        enum_node_states = gdb.lookup_type("enum node_states")

        N_POSSIBLE = enum_node_states["N_POSSIBLE"].enumval
        N_ONLINE = enum_node_states["N_ONLINE"].enumval

        bits = node_states[N_POSSIBLE]["bits"]
        cls.nids_possible = list(for_each_set_bit(bits))

        bits = node_states[N_ONLINE]["bits"]
        cls.nids_online = list(for_each_set_bit(bits))
Example #7
0
 def setup_directmap_base(cls, symbol: gdb.Symbol) -> None:
     cls.directmap_base = int(symbol.value())
Example #8
0
 def setup_vmemmap_base(cls, symbol: gdb.Symbol) -> None:
     cls.vmemmap_base = int(symbol.value())
     # setup_page_type() was first and used the hardcoded initial value,
     # we have to update
     cls.vmemmap = gdb.Value(cls.vmemmap_base).cast(
         types.page_type.pointer())
Example #9
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()
Example #10
0
 def callback(self, value: gdb.Symbol) -> None:
     symval = value.value()
     if symval.type.code == gdb.TYPE_CODE_FUNC:
         symval = symval.address
     self.value = symval