2 # gdb helper commands and functions for Linux kernel debugging
6 # Copyright (c) Siemens AG, 2011-2013
11 # This work is licensed under the terms of the GNU GPL version 2.
16 from linux import tasks, utils
22 def get_current_cpu():
23 if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
24 return gdb.selected_thread().num - 1
25 elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
26 tid = gdb.selected_thread().ptid[2]
27 if tid > (0x100000000 - MAX_CPUS - 2):
28 return 0x100000000 - tid - 2
30 return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
32 raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
33 "supported with this gdb server.")
36 def per_cpu(var_ptr, cpu):
38 cpu = get_current_cpu()
39 if utils.is_target_arch("sparc:v9"):
40 offset = gdb.parse_and_eval(
41 "trap_block[{0}].__per_cpu_base".format(str(cpu)))
44 offset = gdb.parse_and_eval(
45 "__per_cpu_offset[{0}]".format(str(cpu)))
49 pointer = var_ptr.cast(utils.get_long_type()) + offset
50 return pointer.cast(var_ptr.type).dereference()
56 def cpu_mask_invalidate(event):
59 gdb.events.stop.disconnect(cpu_mask_invalidate)
60 if hasattr(gdb.events, 'new_objfile'):
61 gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
64 def cpu_list(mask_name):
67 if mask_name in cpu_mask:
68 mask = cpu_mask[mask_name]
70 mask = gdb.parse_and_eval(mask_name + ".bits")
71 if hasattr(gdb, 'events'):
72 cpu_mask[mask_name] = mask
73 gdb.events.stop.connect(cpu_mask_invalidate)
74 if hasattr(gdb.events, 'new_objfile'):
75 gdb.events.new_objfile.connect(cpu_mask_invalidate)
76 bits_per_entry = mask[0].type.sizeof * 8
77 num_entries = mask.type.sizeof * 8 / bits_per_entry
84 if entry == num_entries:
95 cpu = entry * bits_per_entry + bit
103 class PerCpu(gdb.Function):
104 """Return per-cpu variable.
106 $lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
107 given CPU number. If CPU is omitted, the CPU of the current context is used.
108 Note that VAR has to be quoted as string."""
111 super(PerCpu, self).__init__("lx_per_cpu")
113 def invoke(self, var_name, cpu=-1):
114 var_ptr = gdb.parse_and_eval("&" + var_name.string())
115 return per_cpu(var_ptr, cpu)
121 class LxCurrentFunc(gdb.Function):
122 """Return current task.
124 $lx_current([CPU]): Return the per-cpu task variable for the given CPU
125 number. If CPU is omitted, the CPU of the current context is used."""
128 super(LxCurrentFunc, self).__init__("lx_current")
130 def invoke(self, cpu=-1):
131 var_ptr = gdb.parse_and_eval("¤t_task")
132 return per_cpu(var_ptr, cpu).dereference()