162306a36Sopenharmony_ci#
262306a36Sopenharmony_ci# gdb helper commands and functions for Linux kernel debugging
362306a36Sopenharmony_ci#
462306a36Sopenharmony_ci#  module tools
562306a36Sopenharmony_ci#
662306a36Sopenharmony_ci# Copyright (c) Siemens AG, 2013
762306a36Sopenharmony_ci#
862306a36Sopenharmony_ci# Authors:
962306a36Sopenharmony_ci#  Jan Kiszka <jan.kiszka@siemens.com>
1062306a36Sopenharmony_ci#
1162306a36Sopenharmony_ci# This work is licensed under the terms of the GNU GPL version 2.
1262306a36Sopenharmony_ci#
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ciimport gdb
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cifrom linux import cpus, utils, lists, constants
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_cimodule_type = utils.CachedType("struct module")
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cidef module_list():
2362306a36Sopenharmony_ci    global module_type
2462306a36Sopenharmony_ci    modules = utils.gdb_eval_or_none("modules")
2562306a36Sopenharmony_ci    if modules is None:
2662306a36Sopenharmony_ci        return
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci    module_ptr_type = module_type.get_type().pointer()
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci    for module in lists.list_for_each_entry(modules, module_ptr_type, "list"):
3162306a36Sopenharmony_ci        yield module
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cidef find_module_by_name(name):
3562306a36Sopenharmony_ci    for module in module_list():
3662306a36Sopenharmony_ci        if module['name'].string() == name:
3762306a36Sopenharmony_ci            return module
3862306a36Sopenharmony_ci    return None
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ciclass LxModule(gdb.Function):
4262306a36Sopenharmony_ci    """Find module by name and return the module variable.
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci$lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules
4562306a36Sopenharmony_ciof the target and return that module variable which MODULE matches."""
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci    def __init__(self):
4862306a36Sopenharmony_ci        super(LxModule, self).__init__("lx_module")
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci    def invoke(self, mod_name):
5162306a36Sopenharmony_ci        mod_name = mod_name.string()
5262306a36Sopenharmony_ci        module = find_module_by_name(mod_name)
5362306a36Sopenharmony_ci        if module:
5462306a36Sopenharmony_ci            return module.dereference()
5562306a36Sopenharmony_ci        else:
5662306a36Sopenharmony_ci            raise gdb.GdbError("Unable to find MODULE " + mod_name)
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ciLxModule()
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ciclass LxLsmod(gdb.Command):
6362306a36Sopenharmony_ci    """List currently loaded modules."""
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci    _module_use_type = utils.CachedType("struct module_use")
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci    def __init__(self):
6862306a36Sopenharmony_ci        super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA)
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci    def invoke(self, arg, from_tty):
7162306a36Sopenharmony_ci        gdb.write(
7262306a36Sopenharmony_ci            "Address{0}    Module                  Size  Used by\n".format(
7362306a36Sopenharmony_ci                "        " if utils.get_long_type().sizeof == 8 else ""))
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci        for module in module_list():
7662306a36Sopenharmony_ci            text = module['mem'][constants.LX_MOD_TEXT]
7762306a36Sopenharmony_ci            text_addr = str(text['base']).split()[0]
7862306a36Sopenharmony_ci            total_size = 0
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci            for i in range(constants.LX_MOD_TEXT, constants.LX_MOD_RO_AFTER_INIT + 1):
8162306a36Sopenharmony_ci                total_size += module['mem'][i]['size']
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci            gdb.write("{address} {name:<19} {size:>8}  {ref}".format(
8462306a36Sopenharmony_ci                address=text_addr,
8562306a36Sopenharmony_ci                name=module['name'].string(),
8662306a36Sopenharmony_ci                size=str(total_size),
8762306a36Sopenharmony_ci                ref=str(module['refcnt']['counter'] - 1)))
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci            t = self._module_use_type.get_type().pointer()
9062306a36Sopenharmony_ci            first = True
9162306a36Sopenharmony_ci            sources = module['source_list']
9262306a36Sopenharmony_ci            for use in lists.list_for_each_entry(sources, t, "source_list"):
9362306a36Sopenharmony_ci                gdb.write("{separator}{name}".format(
9462306a36Sopenharmony_ci                    separator=" " if first else ",",
9562306a36Sopenharmony_ci                    name=use['source']['name'].string()))
9662306a36Sopenharmony_ci                first = False
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci            gdb.write("\n")
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ciLxLsmod()
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cidef help():
10362306a36Sopenharmony_ci    t = """Usage: lx-getmod-by-textaddr [Heximal Address]
10462306a36Sopenharmony_ci    Example: lx-getmod-by-textaddr 0xffff800002d305ac\n"""
10562306a36Sopenharmony_ci    gdb.write("Unrecognized command\n")
10662306a36Sopenharmony_ci    raise gdb.GdbError(t)
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ciclass LxFindTextAddrinMod(gdb.Command):
10962306a36Sopenharmony_ci    '''Look up loaded kernel module by text address.'''
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci    def __init__(self):
11262306a36Sopenharmony_ci        super(LxFindTextAddrinMod, self).__init__('lx-getmod-by-textaddr', gdb.COMMAND_SUPPORT)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci    def invoke(self, arg, from_tty):
11562306a36Sopenharmony_ci        args = gdb.string_to_argv(arg)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci        if len(args) != 1:
11862306a36Sopenharmony_ci            help()
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci        addr = gdb.Value(int(args[0], 16)).cast(utils.get_ulong_type())
12162306a36Sopenharmony_ci        for mod in module_list():
12262306a36Sopenharmony_ci            mod_text_start = mod['mem'][constants.LX_MOD_TEXT]['base']
12362306a36Sopenharmony_ci            mod_text_end = mod_text_start + mod['mem'][constants.LX_MOD_TEXT]['size'].cast(utils.get_ulong_type())
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci            if addr >= mod_text_start and addr < mod_text_end:
12662306a36Sopenharmony_ci                s = "0x%x" % addr + " is in " + mod['name'].string() + ".ko\n"
12762306a36Sopenharmony_ci                gdb.write(s)
12862306a36Sopenharmony_ci                return
12962306a36Sopenharmony_ci        gdb.write("0x%x is not in any module text section\n" % addr)
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ciLxFindTextAddrinMod()
132