^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) # common utilities
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) class CachedType:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) def __init__(self, name):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) self._type = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) self._name = name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) def _new_objfile_handler(self, event):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) self._type = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) gdb.events.new_objfile.disconnect(self._new_objfile_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) def get_type(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if self._type is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) self._type = gdb.lookup_type(self._name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) if self._type is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) raise gdb.GdbError(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) "cannot resolve type '{0}'".format(self._name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) gdb.events.new_objfile.connect(self._new_objfile_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return self._type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) long_type = CachedType("long")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) def get_long_type():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) global long_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return long_type.get_type()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) def offset_of(typeobj, field):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) element = gdb.Value(0).cast(typeobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return int(str(element[field].address).split()[0], 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) def container_of(ptr, typeobj, member):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return (ptr.cast(get_long_type()) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) offset_of(typeobj, member)).cast(typeobj)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) class ContainerOf(gdb.Function):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) """Return pointer to containing data structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) $container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) data structure of the type TYPE in which PTR is the address of ELEMENT.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) Note that TYPE and ELEMENT have to be quoted as strings."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) def __init__(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) super(ContainerOf, self).__init__("container_of")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) def invoke(self, ptr, typename, elementname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) elementname.string())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ContainerOf()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) BIG_ENDIAN = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) LITTLE_ENDIAN = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) target_endianness = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) def get_target_endianness():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) global target_endianness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if target_endianness is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) endian = gdb.execute("show endian", to_string=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if "little endian" in endian:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) target_endianness = LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) elif "big endian" in endian:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) target_endianness = BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) raise gdb.GdbError("unknown endianness '{0}'".format(str(endian)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return target_endianness
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) def read_memoryview(inf, start, length):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return memoryview(inf.read_memory(start, length))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) def read_u16(buffer, offset):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) buffer_val = buffer[offset:offset + 2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) value = [0, 0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if type(buffer_val[0]) is str:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) value[0] = ord(buffer_val[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) value[1] = ord(buffer_val[1])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) value[0] = buffer_val[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) value[1] = buffer_val[1]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if get_target_endianness() == LITTLE_ENDIAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return value[0] + (value[1] << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return value[1] + (value[0] << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) def read_u32(buffer, offset):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if get_target_endianness() == LITTLE_ENDIAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return read_u16(buffer, offset) + (read_u16(buffer, offset + 2) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return read_u16(buffer, offset + 2) + (read_u16(buffer, offset) << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) def read_u64(buffer, offset):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if get_target_endianness() == LITTLE_ENDIAN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return read_u32(buffer, offset) + (read_u32(buffer, offset + 4) << 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) def read_ulong(buffer, offset):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if get_long_type().sizeof == 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return read_u64(buffer, offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return read_u32(buffer, offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) target_arch = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) def is_target_arch(arch):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if hasattr(gdb.Frame, 'architecture'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) return arch in gdb.newest_frame().architecture().name()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) global target_arch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if target_arch is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) target_arch = gdb.execute("show architecture", to_string=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return arch in target_arch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) GDBSERVER_QEMU = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) GDBSERVER_KGDB = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) gdbserver_type = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) def get_gdbserver_type():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) def exit_handler(event):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) global gdbserver_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) gdbserver_type = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) gdb.events.exited.disconnect(exit_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) def probe_qemu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return gdb.execute("monitor info version", to_string=True) != ""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) except gdb.error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) def probe_kgdb():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) thread_info = gdb.execute("info thread 2", to_string=True)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return "shadowCPU0" in thread_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) except gdb.error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) global gdbserver_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if gdbserver_type is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if probe_qemu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) gdbserver_type = GDBSERVER_QEMU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) elif probe_kgdb():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) gdbserver_type = GDBSERVER_KGDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if gdbserver_type is not None and hasattr(gdb, 'events'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) gdb.events.exited.connect(exit_handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return gdbserver_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) def gdb_eval_or_none(expresssion):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return gdb.parse_and_eval(expresssion)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) except gdb.error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) def dentry_name(d):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) parent = d['d_parent']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if parent == d or parent == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return ""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) p = dentry_name(d['d_parent']) + "/"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return p + d['d_iname'].string()