#
# gdb helper commands and functions for Linux kernel debugging
#
#  load kernel and module symbols
#
# Copyright (c) Siemens AG, 2011-2013
#
# Authors:
#  Jan Kiszka <jan.kiszka@siemens.com>
#
# This work is licensed under the terms of the GNU GPL version 2.
#

import gdb
import os
import re
import string

from linux import modules, utils


if hasattr(gdb, 'Breakpoint'):
    class LoadModuleBreakpoint(gdb.Breakpoint):
        def __init__(self, spec, gdb_command):
            super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
            self.silent = True
            self.gdb_command = gdb_command

        def stop(self):
            module = gdb.parse_and_eval("mod")
            module_name = module['name'].string()
            cmd = self.gdb_command

            # enforce update if object file is not found
            cmd.module_files_updated = False

            if module_name in cmd.loaded_modules:
                gdb.write("refreshing all symbols to reload module "
                          "'{0}'\n".format(module_name))
                cmd.load_all_symbols()
            else:
                cmd.load_module_symbols(module)
            return False


class LxSymbols(gdb.Command):
    """(Re-)load symbols of Linux kernel and currently loaded modules.

The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
are scanned recursively, starting in the same directory. Optionally, the module
search path can be extended by a space separated list of paths passed to the
lx-symbols command."""

    module_paths = []
    module_files = []
    module_files_updated = False
    loaded_modules = []
    breakpoint = None

    def __init__(self):
        super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
                                        gdb.COMPLETE_FILENAME)

    def _update_module_files(self):
        self.module_files = []
        for path in self.module_paths:
            gdb.write("scanning for modules in {0}\n".format(path))
            for root, dirs, files in os.walk(path):
                for name in files:
                    if name.endswith(".ko"):
                        self.module_files.append(root + "/" + name)
        self.module_files_updated = True

    def _get_module_file(self, module_name):
        module_pattern = ".*/{0}\.ko$".format(
            module_name.replace("_", r"[_\-]"))
        for name in self.module_files:
            if re.match(module_pattern, name) and os.path.exists(name):
                return name
        return None

    def _section_arguments(self, module):
        try:
            sect_attrs = module['sect_attrs'].dereference()
        except gdb.error:
            return ""
        attrs = sect_attrs['attrs']
        section_name_to_address = {
            attrs[n]['name'].string() : attrs[n]['address']
            for n in range(int(sect_attrs['nsections']))}
        args = []
        for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
            address = section_name_to_address.get(section_name)
            if address:
                args.append(" -s {name} {addr}".format(
                    name=section_name, addr=str(address)))
        return "".join(args)

    def load_module_symbols(self, module):
        module_name = module['name'].string()
        module_addr = str(module['module_core']).split()[0]

        module_file = self._get_module_file(module_name)
        if not module_file and not self.module_files_updated:
            self._update_module_files()
            module_file = self._get_module_file(module_name)

        if module_file:
            gdb.write("loading @{addr}: {filename}\n".format(
                addr=module_addr, filename=module_file))
            cmdline = "add-symbol-file {filename} {addr}{sections}".format(
                filename=module_file,
                addr=module_addr,
                sections=self._section_arguments(module))
            gdb.execute(cmdline, to_string=True)
            if not module_name in self.loaded_modules:
                self.loaded_modules.append(module_name)
        else:
            gdb.write("no module object found for '{0}'\n".format(module_name))

    def load_all_symbols(self):
        gdb.write("loading vmlinux\n")

        # Dropping symbols will disable all breakpoints. So save their states
        # and restore them afterward.
        saved_states = []
        if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
            for bp in gdb.breakpoints():
                saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})

        # drop all current symbols and reload vmlinux
        gdb.execute("symbol-file", to_string=True)
        gdb.execute("symbol-file vmlinux")

        self.loaded_modules = []
        module_list = modules.module_list()
        if not module_list:
            gdb.write("no modules found\n")
        else:
            [self.load_module_symbols(module) for module in module_list]

        for saved_state in saved_states:
            saved_state['breakpoint'].enabled = saved_state['enabled']

    def invoke(self, arg, from_tty):
        self.module_paths = arg.split()
        self.module_paths.append(os.getcwd())

        # enforce update
        self.module_files = []
        self.module_files_updated = False

        self.load_all_symbols()

        if hasattr(gdb, 'Breakpoint'):
            if not self.breakpoint is None:
                self.breakpoint.delete()
                self.breakpoint = None
            self.breakpoint = LoadModuleBreakpoint(
                "kernel/module.c:do_init_module", self)
        else:
            gdb.write("Note: symbol update on module loading not supported "
                      "with this gdb version\n")


LxSymbols()
