Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) # gdb helper commands and functions for Linux kernel debugging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) #  load kernel and module symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) # Copyright (c) Siemens AG, 2011-2013
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) # Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #  Jan Kiszka <jan.kiszka@siemens.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) # This work is licensed under the terms of the GNU GPL version 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) import gdb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) import re
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) from linux import modules, utils
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) if hasattr(gdb, 'Breakpoint'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)     class LoadModuleBreakpoint(gdb.Breakpoint):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)         def __init__(self, spec, gdb_command):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)             super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)             self.silent = True
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)             self.gdb_command = gdb_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)         def stop(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)             module = gdb.parse_and_eval("mod")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)             module_name = module['name'].string()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)             cmd = self.gdb_command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)             # enforce update if object file is not found
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)             cmd.module_files_updated = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)             # Disable pagination while reporting symbol (re-)loading.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)             # The console input is blocked in this context so that we would
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)             # get stuck waiting for the user to acknowledge paged output.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)             show_pagination = gdb.execute("show pagination", to_string=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40)             pagination = show_pagination.endswith("on.\n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)             gdb.execute("set pagination off")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)             if module_name in cmd.loaded_modules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)                 gdb.write("refreshing all symbols to reload module "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)                           "'{0}'\n".format(module_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)                 cmd.load_all_symbols()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)             else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48)                 cmd.load_module_symbols(module)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)             # restore pagination state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)             gdb.execute("set pagination %s" % ("on" if pagination else "off"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)             return False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) class LxSymbols(gdb.Command):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)     """(Re-)load symbols of Linux kernel and currently loaded modules.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) are scanned recursively, starting in the same directory. Optionally, the module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) search path can be extended by a space separated list of paths passed to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) lx-symbols command."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)     module_paths = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)     module_files = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)     module_files_updated = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)     loaded_modules = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)     breakpoint = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)     def __init__(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)         super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)                                         gdb.COMPLETE_FILENAME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)     def _update_module_files(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)         self.module_files = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)         for path in self.module_paths:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)             gdb.write("scanning for modules in {0}\n".format(path))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)             for root, dirs, files in os.walk(path):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)                 for name in files:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)                     if name.endswith(".ko") or name.endswith(".ko.debug"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)                         self.module_files.append(root + "/" + name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)         self.module_files_updated = True
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)     def _get_module_file(self, module_name):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)         module_pattern = ".*/{0}\.ko(?:.debug)?$".format(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)             module_name.replace("_", r"[_\-]"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)         for name in self.module_files:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)             if re.match(module_pattern, name) and os.path.exists(name):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)                 return name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)         return None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)     def _section_arguments(self, module):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)         try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)             sect_attrs = module['sect_attrs'].dereference()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)         except gdb.error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96)             return ""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97)         attrs = sect_attrs['attrs']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)         section_name_to_address = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)             attrs[n]['battr']['attr']['name'].string(): attrs[n]['address']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)             for n in range(int(sect_attrs['nsections']))}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)         args = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)         for section_name in [".data", ".data..read_mostly", ".rodata", ".bss",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)                              ".text", ".text.hot", ".text.unlikely"]:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)             address = section_name_to_address.get(section_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)             if address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)                 args.append(" -s {name} {addr}".format(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)                     name=section_name, addr=str(address)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)         return "".join(args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)     def load_module_symbols(self, module):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)         module_name = module['name'].string()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)         module_addr = str(module['core_layout']['base']).split()[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)         module_file = self._get_module_file(module_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)         if not module_file and not self.module_files_updated:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)             self._update_module_files()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)             module_file = self._get_module_file(module_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)         if module_file:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)             if utils.is_target_arch('s390'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)                 # Module text is preceded by PLT stubs on s390.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)                 module_arch = module['arch']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)                 plt_offset = int(module_arch['plt_offset'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)                 plt_size = int(module_arch['plt_size'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)                 module_addr = hex(int(module_addr, 0) + plt_offset + plt_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)             gdb.write("loading @{addr}: {filename}\n".format(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)                 addr=module_addr, filename=module_file))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)             cmdline = "add-symbol-file {filename} {addr}{sections}".format(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)                 filename=module_file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)                 addr=module_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)                 sections=self._section_arguments(module))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)             gdb.execute(cmdline, to_string=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)             if module_name not in self.loaded_modules:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)                 self.loaded_modules.append(module_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)             gdb.write("no module object found for '{0}'\n".format(module_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)     def load_all_symbols(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)         gdb.write("loading vmlinux\n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)         # Dropping symbols will disable all breakpoints. So save their states
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)         # and restore them afterward.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)         saved_states = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)         if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)             for bp in gdb.breakpoints():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)                 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)         # drop all current symbols and reload vmlinux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)         orig_vmlinux = 'vmlinux'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)         for obj in gdb.objfiles():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)             if obj.filename.endswith('vmlinux'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)                 orig_vmlinux = obj.filename
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)         gdb.execute("symbol-file", to_string=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)         gdb.execute("symbol-file {0}".format(orig_vmlinux))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)         self.loaded_modules = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)         module_list = modules.module_list()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)         if not module_list:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)             gdb.write("no modules found\n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)             [self.load_module_symbols(module) for module in module_list]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)         for saved_state in saved_states:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)             saved_state['breakpoint'].enabled = saved_state['enabled']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)     def invoke(self, arg, from_tty):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)         self.module_paths = [os.path.expanduser(p) for p in arg.split()]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)         self.module_paths.append(os.getcwd())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)         # enforce update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)         self.module_files = []
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)         self.module_files_updated = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)         self.load_all_symbols()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)         if hasattr(gdb, 'Breakpoint'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)             if self.breakpoint is not None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)                 self.breakpoint.delete()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)                 self.breakpoint = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)             self.breakpoint = LoadModuleBreakpoint(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)                 "kernel/module.c:do_init_module", self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)             gdb.write("Note: symbol update on module loading not supported "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)                       "with this gdb version\n")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) LxSymbols()