Exemplo n.º 1
0
    def execute(self, argv):
        super_blocks = gdb.lookup_symbol('super_blocks', None)[0].value()
        sbtype = gdb.lookup_type('struct super_block')

        try:
            btrfs_fs_info_type = gdb.lookup_type('struct btrfs_fs_info')
        except gdb.error:
            # Load the module if it's not loaded yet
            module_type = gdb.lookup_type('struct module')

            modules = gdb.lookup_symbol('modules', None)[0].value()
            for module in list_for_each_entry(modules, module_type, 'list'):
                if module['name'].string() == "btrfs":
                    addr = module['module_core']
                    gdb.execute("add-symbol-file {} {}".format(path, addr))
            btrfs_fs_info_type = gdb.lookup_type('struct btrfs_fs_info')

        for sb in list_for_each_entry(super_blocks, sbtype, 's_list'):
            if sb['s_type']['name'].string() == "btrfs":
                fs_info = gdb.Value(sb['s_fs_info']).cast(btrfs_fs_info_type.pointer())

                u = long(0)
                for i in range(0, 16):
                    u <<= 8
                    u += int(fs_info['fsid'][i])
                u = uuid.UUID(int=u)
                print "{} -> {} {}".format(sb.address, sb['s_id'].string(), u)
Exemplo n.º 2
0
    def execute(self, argv):
        super_blocks = gdb.lookup_symbol('super_blocks', None)[0].value()
        sbtype = gdb.lookup_type('struct super_block')

        try:
            btrfs_fs_info_type = gdb.lookup_type('struct btrfs_fs_info')
        except gdb.error:
            # Load the module if it's not loaded yet
            module_type = gdb.lookup_type('struct module')

            modules = gdb.lookup_symbol('modules', None)[0].value()
            for module in list_for_each_entry(modules, module_type, 'list'):
                if module['name'].string() == "btrfs":
                    addr = module['module_core']
                    gdb.execute("add-symbol-file {} {}".format(path, addr))
            btrfs_fs_info_type = gdb.lookup_type('struct btrfs_fs_info')

        for sb in list_for_each_entry(super_blocks, sbtype, 's_list'):
            if sb['s_type']['name'].string() == "btrfs":
                fs_info = gdb.Value(sb['s_fs_info']).cast(
                    btrfs_fs_info_type.pointer())

                u = 0
                for i in range(0, 16):
                    u <<= 8
                    u += int(fs_info['fsid'][i])
                u = uuid.UUID(int=u)
                print "{} -> {} {}".format(sb.address, sb['s_id'].string(), u)
Exemplo n.º 3
0
    def setup_tasks(self):
        gdb.execute('set print thread-events 0')

        init_task = gdb.lookup_global_symbol('init_task')
        task_list = init_task.value()['tasks']
        runqueues = gdb.lookup_global_symbol('runqueues')

        rqs = get_percpu_var(runqueues)
        rqscurrs = {long(x["curr"]): k for (k, x) in rqs.items()}

        self.pid_to_task_struct = {}

        print("Loading tasks...", end='')
        sys.stdout.flush()

        task_count = 0
        tasks = []
        for taskg in list_for_each_entry(task_list,
                                         init_task.type,
                                         'tasks',
                                         include_head=True):
            tasks.append(taskg)
            for task in list_for_each_entry(taskg['thread_group'],
                                            init_task.type, 'thread_group'):
                tasks.append(task)

        for task in tasks:
            cpu = None
            regs = None
            active = long(task.address) in rqscurrs
            if active:
                cpu = rqscurrs[long(task.address)]
                regs = self.vmcore.attr.cpu[cpu].reg

            ltask = LinuxTask(task, active, cpu, regs)
            ptid = (LINUX_KERNEL_PID, task['pid'], 0)
            try:
                thread = gdb.selected_inferior().new_thread(ptid, ltask)
            except gdb.error as e:
                print("Failed to setup task @{:#x}".format(long(task.address)))
                continue
            thread.name = task['comm'].string()

            self.target.arch.setup_thread_info(thread)
            ltask.attach_thread(thread)
            ltask.set_get_stack_pointer(self.target.arch.get_stack_pointer)

            crash.cache.tasks.cache_task(ltask)

            task_count += 1
            if task_count % 100 == 0:
                print(".", end='')
                sys.stdout.flush()
        print(" done. ({} tasks total)".format(task_count))

        gdb.selected_inferior().executing = False
Exemplo n.º 4
0
    def setup_tasks(self):
        init_task = gdb.lookup_global_symbol('init_task')
        task_list = init_task.value()['tasks']
        runqueues = gdb.lookup_global_symbol('runqueues')

        rqs = get_percpu_var(runqueues)
        rqscurrs = {long(x["curr"]) : k for (k, x) in rqs.items()}

        self.pid_to_task_struct = {}

        print("Loading tasks...", end='')
        sys.stdout.flush()

        task_count = 0
        tasks = []
        for taskg in list_for_each_entry(task_list, init_task.type, 'tasks'):
            tasks.append(taskg)
            for task in list_for_each_entry(taskg['thread_group'], init_task.type, 'thread_group'):
                tasks.append(task)

        for task in tasks:
            cpu = None
            regs = None
            active = long(task.address) in rqscurrs
            if active:
                cpu = rqscurrs[long(task.address)]
                regs = self.kdump.attr.cpu[cpu].reg

            ltask = LinuxTask(task, active, cpu, regs)
            ptid = (LINUX_KERNEL_PID, task['pid'], 0)
            try:
                thread = gdb.selected_inferior().new_thread(ptid, ltask)
            except gdb.error as e:
                print("Failed to setup task @{:#x}".format(long(task.address)))
                continue
            thread.name = task['comm'].string()

            self.arch.setup_thread_info(thread)
            ltask.attach_thread(thread)
            ltask.set_get_stack_pointer(self.arch.get_stack_pointer)

            crash.cache.tasks.cache_task(ltask)

            task_count += 1
            if task_count % 100 == 0:
                print(".", end='')
                sys.stdout.flush()
        print(" done. ({} tasks total)".format(task_count))

        gdb.selected_inferior().executing = False
Exemplo n.º 5
0
 def get_block_device(self):
     all_bdevs = gdb.lookup_symbol('all_bdevs', None)[0].value()
     for bdev in list_for_each_entry(all_bdevs, self.block_device_type,
         'bd_list'):
         if int(bdev['bd_disk']) != 0 and int(bdev['bd_part']) != 0:
             return bdev
     return None
Exemplo n.º 6
0
 def get_hd_struct(self):
     all_bdevs = gdb.lookup_symbol('all_bdevs', None)[0].value()
     for bdev in list_for_each_entry(all_bdevs, self.block_device_type,
         'bd_list'):
         if int(bdev['bd_part']) != 0:
             return bdev['bd_part'].dereference()
     return None
Exemplo n.º 7
0
def klist_for_each(klist: gdb.Value) -> Iterable[gdb.Value]:
    """
    Iterate over a klist and yield each node

    Args:
        klist: The list to iterate.  The value must be of type
            ``struct klist`` or ``struct klist *``.

    Yields:
        :obj:`gdb.Value`: The next node in the list.  The value is of type
            ``struct klist_node``.
    """
    if klist.type == types.klist_type.pointer():
        klist = klist.dereference()
    elif klist.type != types.klist_type:
        raise InvalidArgumentError(
            "klist must be gdb.Value representing 'struct klist' or 'struct klist *' not {}"
            .format(klist.type))
    if klist.type is not types.klist_type:
        types.override('struct klist', klist.type)

    for node in list_for_each_entry(klist['k_list'], types.klist_node_type,
                                    'n_node'):
        if node['n_klist'] != klist.address:
            raise KlistCorruptedError("Corrupted")
        yield node
Exemplo n.º 8
0
 def _check_free_area(self, area: gdb.Value, is_pcp: bool) -> None:
     nr_free = 0
     if is_pcp:
         list_array_name = "lists"
         error_desc = "pcplist"
     else:
         list_array_name = "free_list"
         error_desc = "free area"
     for free_list in array_for_each(area[list_array_name]):
         try:
             for page_obj in list_for_each_entry(free_list,
                                                 self.types.page_type,
                                                 "lru"):
                 page = crash.types.page.Page.from_obj(page_obj)
                 nr_free += 1
                 if page.get_nid() != self.nid or page.get_zid(
                 ) != self.zid:
                     print(
                         f"page 0x{int(page_obj.address):x} misplaced on "
                         f"{error_desc} of node {self.nid} zone {self.zid}, "
                         f"has flags for node {page.get_nid()} zone {page.get_zid()}"
                     )
         except BufferError as e:
             print(f"Error traversing free area: {e}")
     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}: "
               f"expected {nr_expected}, counted {nr_free}")
Exemplo n.º 9
0
 def _for_each_mount_nsproxy(self, task: gdb.Value) -> Iterator[gdb.Value]:
     """
     An implementation of for_each_mount that uses the task's
     nsproxy to locate the mount namespace.  See :ref:`for_each_mount`
     for more details.
     """
     return list_for_each_entry(task['nsproxy']['mnt_ns']['list'],
                                types.mount_type, 'mnt_list')
Exemplo n.º 10
0
def inode_paths(inode):
    for dentry in list_for_each_entry(inode['i_dentry'], dentry_type, ''):
        names = [dentry['d_name']['name'].string()]
        parent = dentry['d_parent']
        while parent.address != parent['d_parent'].address:
            names.insert(0, parent['d_name']['name'].string())
            parent = parent['d_parent']

        yield '/'.join(names)
Exemplo n.º 11
0
    def test_normal_container_list_with_string(self):
        normal_list = get_symbol("good_container_list")
        short_list = get_symbol("good_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof

        with self.assertRaises(ArgumentTypeError):
            for node in list_for_each_entry(normal_list, 'struct container',
                                            'list'):
                count += 1
Exemplo n.º 12
0
    def test_normal_container_list_with_type(self):
        normal_list = get_symbol("good_container_list")
        short_list = get_symbol("good_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof
        struct_container = gdb.lookup_type('struct container')

        count = 0
        for node in list_for_each_entry(normal_list, struct_container, 'list'):
            count += 1
Exemplo n.º 13
0
    def test_bad_container_list_with_string(self):
        bad_list = get_symbol("bad_container_list")
        short_list = get_symbol("bad_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof

        count = 0
        with self.assertRaises(CorruptListError):
            for node in list_for_each_entry(bad_list, 'struct container',
                                            'list'):
                count += 1
Exemplo n.º 14
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
Exemplo n.º 15
0
    def test_bad_container_list_with_string(self):
        bad_list = get_symbol("bad_container_list")
        short_list = get_symbol("bad_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof

        count = 0
        with self.assertRaises(ArgumentTypeError):
            for node in list_for_each_entry(bad_list, 'struct container',
                                            'list', print_broken_links=False):
                count += 1
Exemplo n.º 16
0
    def execute(self, args: argparse.Namespace) -> None:
        regex = None
        print_header = True
        if args.args:
            regex = re.compile(fnmatch.translate(args.args[0]))

        core_layout = None

        for mod in for_each_module():
            if core_layout is None:
                core_layout = struct_has_member(mod.type, 'core_layout')

            modname = mod['name'].string()
            if regex:
                m = regex.match(modname)
                if m is None:
                    continue

            if args.p is not None:
                if print_header:
                    print_header = False
                    if args.p == -1:
                        print("Module\t\t\tPercpu Base\t\tSize")
                    else:
                        print("Module\t\t\tPercpu Base@CPU{:d}\t\tSize".format(
                            args.p))
                self.print_module_percpu(mod, args.p)
                continue

            if print_header:
                print_header = False
                print("Module\t\t\tAddress\t\t\tSize\tUsed by")

            if core_layout:
                addr = int(mod['core_layout']['base'])
                size = int(mod['core_layout']['size'])
            else:
                addr = int(mod['module_core'])
                size = int(mod['core_size'])

            module_use = ""
            count = 0
            for use in list_for_each_entry(mod['source_list'],
                                           types.module_use_type,
                                           'source_list'):
                if module_use == "":
                    module_use += " "
                else:
                    module_use += ","
                module_use += use['source']['name'].string()
                count += 1

            print("{:16s}\t{:#x}\t{:d}\t{:d}{}".format(modname, addr, size,
                                                       count, module_use))
Exemplo n.º 17
0
    def test_bad_container_list_with_type(self):
        bad_list = get_symbol("bad_container_list")
        short_list = get_symbol("bad_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof
        struct_container = gdb.lookup_type('struct container')

        count = 0
        with self.assertRaises(CorruptListError):
            for node in list_for_each_entry(bad_list, struct_container,
                                            'list', print_broken_links=False):
                count += 1
Exemplo n.º 18
0
 def _setup_dynamic_offset_cache(self) -> None:
     # TODO: interval tree would be more efficient, but this adds no 3rd
     # party module dependency...
     use_area_map = struct_has_member(types.pcpu_chunk_type, 'map')
     for slot in range(symvals.pcpu_nr_slots):
         for chunk in list_for_each_entry(symvals.pcpu_slot[slot],
                                          types.pcpu_chunk_type, 'list'):
             if use_area_map:
                 self._setup_dynamic_offset_cache_area_map(chunk)
             else:
                 self._setup_dynamic_offset_cache_bitmap(chunk)
Exemplo n.º 19
0
    def test_cycle_container_list_with_type(self):
        cycle_list = get_symbol("cycle_container_list")
        short_list = get_symbol("cycle_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof
        struct_container = gdb.lookup_type('struct container')

        count = 0
        with self.assertRaises(ListCycleError):
            for node in list_for_each_entry(cycle_list, struct_container,
                                            'list'):
                count += 1
Exemplo n.º 20
0
    def test_normal_container_list_with_string(self):
        normal_list = get_symbol("good_container_list")
        short_list = get_symbol("good_containers")
        expected_count = short_list.type.sizeof // short_list[0].type.sizeof

        count = 0
        for node in list_for_each_entry(normal_list, 'struct container',
                                        'list'):
            count += 1

        self.assertTrue(count == expected_count)
Exemplo n.º 21
0
    def klist_for_each(self, klist):
        if klist.type == self.klist_type.pointer():
            klist = klist.dereference()
        elif klist.type != self.klist_type:
            raise TypeError("klist must be gdb.Value representing 'struct klist' or 'struct klist *' not {}"
                            .format(klist.type))

        for node in list_for_each_entry(klist['k_list'],
                                        self.klist_node_type, 'n_node'):
            if node['n_klist'] != klist.address:
                raise KlistCorruptedError("Corrupted")
            yield node
Exemplo n.º 22
0
def for_each_thread_group_leader() -> Iterator[gdb.Value]:
    """
    Iterate the task list and yield each thread group leader

    Yields:
        :obj:`gdb.Value`: The next task on the list.  The value is of
        type ``struct task_struct``.
    """
    task_list = symvals.init_task['tasks']
    for task in list_for_each_entry(task_list, symvals.init_task.type,
                                    'tasks', include_head=True):
        yield task
Exemplo n.º 23
0
def for_each_module() -> Iterable[gdb.Value]:
    """
    Iterate over each module in the modules list

    Yields:
        :obj:`gdb.Value`: The next module on the list.  The value is of
        type ``struct module``.

    """
    for module in list_for_each_entry(symvals.modules, types.module_type,
                                      'list'):
        yield module
Exemplo n.º 24
0
    def klist_for_each(self, klist):
        if klist.type == self.klist_type.pointer():
            klist = klist.dereference()
        elif klist.type != self.klist_type:
            raise TypeError(
                "klist must be gdb.Value representing 'struct klist' or 'struct klist *' not {}"
                .format(klist.type))

        for node in list_for_each_entry(klist['k_list'], self.klist_node_type,
                                        'n_node'):
            if node['n_klist'] != klist.address:
                raise KlistCorruptedError("Corrupted")
            yield node
Exemplo n.º 25
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}")
Exemplo n.º 26
0
def for_each_super_block() -> Iterable[gdb.Value]:
    """
    Iterate over the list of super blocks and yield each one.

    Yields:
        :obj:`gdb.Value`: One value for each super block.  Each value
        will be of type ``struct super_block``.

    Raises:
        :obj:`gdb.NotAvailableError`: The target value was not available.
    """
    for sb in list_for_each_entry(symvals.super_blocks, types.super_block_type,
                                  's_list'):
        yield sb
Exemplo n.º 27
0
    def setup_slab_caches(cls, slab_caches):
        cls.kmem_caches = dict()
        cls.kmem_caches_by_addr = dict()

        list_caches = slab_caches.value()

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

            cls.kmem_caches[name] = kmem_cache
            cls.kmem_caches_by_addr[long(cache.address)] = kmem_cache
Exemplo n.º 28
0
def for_each_thread_in_group(task: gdb.Value) -> Iterator[gdb.Value]:
    """
    Iterate a thread group leader's thread list and
    yield each struct task_struct

    Args:
        task: The task_struct that is the thread group leader.  The value
            must be of type ``struct task_struct``.

    Yields:
        :obj:`gdb.Value`: The next task on the list.  The value is of type
        ``struct task_struct``.
    """
    thread_list = task['thread_group']
    for thread in list_for_each_entry(thread_list, symvals.init_task.type,
                                      'thread_group'):
        yield thread
Exemplo n.º 29
0
def xfs_for_each_ail_entry(ail: gdb.Value) -> Iterable[gdb.Value]:
    """
    Iterates over the XFS Active Item Log and returns each item

    Args:
        ail: The XFS AIL to iterate.  The value must be of type
            ``struct xfs_ail``.

    Yields:
        :obj:`gdb.Value`: A log item from the AIL.  Each value will be of
        type ``struct xfs_log_item``.

    Raises:
        :obj:`gdb.NotAvailableError`: The target value was not available.
    """
    head = XFS.get_ail_head(ail)
    for item in list_for_each_entry(head, types.xfs_log_item_type, 'li_ail'):
        yield item
Exemplo n.º 30
0
def for_each_request_in_queue(queue: gdb.Value) -> Iterable[gdb.Value]:
    """
    Iterates over each ``struct request`` in request_queue

    This method iterates over the ``request_queue``'s queuelist and
    returns a request for each member.

    Args:
        queue: The ``struct request_queue`` used to iterate.  The value
            must be of type ``struct request_queue``.

    Yields:
        :obj:`gdb.Value`: Each ``struct request`` contained within the
        ``request_queue``'s queuelist.  The value is of type ``struct request``.
    """
    if int(queue) == 0:
        raise NoQueueError("Queue is NULL")
    return list_for_each_entry(queue['queue_head'], types.request_type,
                               'queuelist')
Exemplo n.º 31
0
    def for_each_request_in_queue(self, queue):
        """
        Iterates over each struct request in request_queue

        This method iterates over the request_queue's queuelist and
        returns a request for each member.

        Args:
            queue(gdb.Value<struct request_queue>): The struct request_queue
                used to iterate

        Yields:
            gdb.Value<struct request>: Each struct request contained within
               the request_queue's queuelist
        """
        if long(queue) == 0:
            raise NoQueueError("Queue is NULL")
        return list_for_each_entry(queue['queue_head'], self.request_type,
                                   'queuelist')
Exemplo n.º 32
0
 def _check_free_area(self, area: gdb.Value, is_pcp: bool) -> None:
     nr_free = 0
     list_array_name = "lists" if is_pcp else "free_list"
     for free_list in array_for_each(area[list_array_name]):
         for page_obj in list_for_each_entry(free_list,
                                             self.types.page_type, "lru"):
             page = crash.types.page.Page.from_obj(page_obj)
             nr_free += 1
             if page.get_nid() != self.nid or page.get_zid() != self.zid:
                 print(
                     "page {:#x} misplaced on {} of zone {}:{}, has flags for zone {}:{}"
                     .format(int(page_obj.address),
                             "pcplist" if is_pcp else "freelist", self.nid,
                             self.zid, page.get_nid(), page.get_zid()))
     nr_expected = area["count"] if is_pcp else area["nr_free"]
     if nr_free != nr_expected:
         print("nr_free mismatch in {} {}: expected {}, counted {}".format(
             "pcplist" if is_pcp else "area", area.address, nr_expected,
             nr_free))
Exemplo n.º 33
0
 def for_each_module(self):
     for module in list_for_each_entry(self.modules, self.module_type,
                                       'list'):
         yield module
Exemplo n.º 34
0
def xfs_for_each_ail_entry(ail):
    xfs_log_item_type = gdb.lookup_type('struct xfs_log_item')
    for item in list_for_each_entry(ail['xa_ail'], xfs_log_item_type,
                                    'li_ail'):
        yield item
Exemplo n.º 35
0
 def for_each_mount_nsproxy(self, task):
     return list_for_each_entry(task['nsproxy']['mnt_ns']['list'],
                                self.mount_type, 'mnt_list')
Exemplo n.º 36
0
 def for_each_request_in_queue(self, queue):
     if long(queue) == 0:
         raise NoQueueError("Queue is NULL")
     return list_for_each_entry(queue['queue_head'], self.request_type,
                                'queuelist')
Exemplo n.º 37
0
#!/usr/bin/env python
# vim:set shiftwidth=4 softtabstop=4 expandtab textwidth=79:

from crash.types.list import list_for_each_entry
import gdb
import uuid
from crash.cache import sys
import os

def find(name, path):
    for root, dirs, files in os.walk(path):
        if name in files:
            return os.path.join(root, name)

sys.cache.init_sys_caches()
path = "/lib/modules/{}".format(sys.cache.utsname_cache['release'])

modules = gdb.lookup_symbol('modules', None)[0].value()
module_type = gdb.lookup_type('struct module')
for module in list_for_each_entry(modules, module_type, 'list'):
    modname = "{}.ko".format(module['name'].string())
    modpath = find(modname, path)
    if not modpath and modname.find('_') != -1:
        modname = modname.replace('_', '-')
        modpath = find(modname, path)
    if not modpath:
        print "Couldn't find {} under {}.".format(module['name'], path)
        continue
    gdb.execute("add-symbol-file {} {}".format(modpath, module['module_core']))