^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) # per-cpu tools
^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) from linux import tasks, utils
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) MAX_CPUS = 4096
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) def get_current_cpu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return gdb.selected_thread().num - 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) tid = gdb.selected_thread().ptid[2]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if tid > (0x100000000 - MAX_CPUS - 2):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return 0x100000000 - tid - 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) "supported with this gdb server.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) def per_cpu(var_ptr, cpu):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if cpu == -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) cpu = get_current_cpu()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if utils.is_target_arch("sparc:v9"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) offset = gdb.parse_and_eval(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) "trap_block[{0}].__per_cpu_base".format(str(cpu)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) try:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) offset = gdb.parse_and_eval(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) "__per_cpu_offset[{0}]".format(str(cpu)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) except gdb.error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) # !CONFIG_SMP case
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) offset = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) pointer = var_ptr.cast(utils.get_long_type()) + offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return pointer.cast(var_ptr.type).dereference()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) cpu_mask = {}
^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) def cpu_mask_invalidate(event):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) global cpu_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) cpu_mask = {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) gdb.events.stop.disconnect(cpu_mask_invalidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if hasattr(gdb.events, 'new_objfile'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) def cpu_list(mask_name):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) global cpu_mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) mask = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if mask_name in cpu_mask:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) mask = cpu_mask[mask_name]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) if mask is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) mask = gdb.parse_and_eval(mask_name + ".bits")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if hasattr(gdb, 'events'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) cpu_mask[mask_name] = mask
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) gdb.events.stop.connect(cpu_mask_invalidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if hasattr(gdb.events, 'new_objfile'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) gdb.events.new_objfile.connect(cpu_mask_invalidate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) bits_per_entry = mask[0].type.sizeof * 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) num_entries = mask.type.sizeof * 8 / bits_per_entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) entry = -1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) bits = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) while True:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) while bits == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) entry += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) if entry == num_entries:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) bits = mask[entry]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if bits != 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) bit = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) break
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) while bits & 1 == 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) bits >>= 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) bit += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) cpu = entry * bits_per_entry + bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) bits >>= 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) bit += 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) yield int(cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) def each_online_cpu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) for cpu in cpu_list("__cpu_online_mask"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) yield cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) def each_present_cpu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) for cpu in cpu_list("__cpu_present_mask"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) yield cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) def each_possible_cpu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) for cpu in cpu_list("__cpu_possible_mask"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) yield cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) def each_active_cpu():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) for cpu in cpu_list("__cpu_active_mask"):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) yield cpu
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) class LxCpus(gdb.Command):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) """List CPU status arrays
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) Displays the known state of each CPU based on the kernel masks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) and can help identify the state of hotplugged CPUs"""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) def __init__(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) super(LxCpus, self).__init__("lx-cpus", gdb.COMMAND_DATA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) def invoke(self, arg, from_tty):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) gdb.write("Possible CPUs : {}\n".format(list(each_possible_cpu())))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) gdb.write("Present CPUs : {}\n".format(list(each_present_cpu())))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) gdb.write("Online CPUs : {}\n".format(list(each_online_cpu())))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) gdb.write("Active CPUs : {}\n".format(list(each_active_cpu())))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) LxCpus()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) class PerCpu(gdb.Function):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) """Return per-cpu variable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) $lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) given CPU number. If CPU is omitted, the CPU of the current context is used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) Note that VAR has to be quoted as string."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) def __init__(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) super(PerCpu, self).__init__("lx_per_cpu")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) def invoke(self, var_name, cpu=-1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) var_ptr = gdb.parse_and_eval("&" + var_name.string())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return per_cpu(var_ptr, cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) PerCpu()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) class LxCurrentFunc(gdb.Function):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) """Return current task.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) $lx_current([CPU]): Return the per-cpu task variable for the given CPU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) number. If CPU is omitted, the CPU of the current context is used."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) def __init__(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) super(LxCurrentFunc, self).__init__("lx_current")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) def invoke(self, cpu=-1):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) var_ptr = gdb.parse_and_eval("¤t_task")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return per_cpu(var_ptr, cpu).dereference()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) LxCurrentFunc()