2015-02-18 00:47:21 +03:00
|
|
|
#
|
|
|
|
# gdb helper commands and functions for Linux kernel debugging
|
|
|
|
#
|
|
|
|
# per-cpu tools
|
|
|
|
#
|
|
|
|
# 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
|
|
|
|
|
|
|
|
from linux import tasks, utils
|
|
|
|
|
|
|
|
|
|
|
|
MAX_CPUS = 4096
|
|
|
|
|
|
|
|
|
|
|
|
def get_current_cpu():
|
|
|
|
if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
|
|
|
|
return gdb.selected_thread().num - 1
|
|
|
|
elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
|
|
|
|
tid = gdb.selected_thread().ptid[2]
|
|
|
|
if tid > (0x100000000 - MAX_CPUS - 2):
|
|
|
|
return 0x100000000 - tid - 2
|
|
|
|
else:
|
|
|
|
return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
|
|
|
|
else:
|
|
|
|
raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
|
|
|
|
"supported with this gdb server.")
|
|
|
|
|
|
|
|
|
|
|
|
def per_cpu(var_ptr, cpu):
|
|
|
|
if cpu == -1:
|
|
|
|
cpu = get_current_cpu()
|
|
|
|
if utils.is_target_arch("sparc:v9"):
|
|
|
|
offset = gdb.parse_and_eval(
|
|
|
|
"trap_block[{0}].__per_cpu_base".format(str(cpu)))
|
|
|
|
else:
|
|
|
|
try:
|
|
|
|
offset = gdb.parse_and_eval(
|
|
|
|
"__per_cpu_offset[{0}]".format(str(cpu)))
|
|
|
|
except gdb.error:
|
|
|
|
# !CONFIG_SMP case
|
|
|
|
offset = 0
|
|
|
|
pointer = var_ptr.cast(utils.get_long_type()) + offset
|
|
|
|
return pointer.cast(var_ptr.type).dereference()
|
|
|
|
|
|
|
|
|
|
|
|
class PerCpu(gdb.Function):
|
|
|
|
"""Return per-cpu variable.
|
|
|
|
|
|
|
|
$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
|
|
|
|
given CPU number. If CPU is omitted, the CPU of the current context is used.
|
|
|
|
Note that VAR has to be quoted as string."""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(PerCpu, self).__init__("lx_per_cpu")
|
|
|
|
|
|
|
|
def invoke(self, var_name, cpu=-1):
|
|
|
|
var_ptr = gdb.parse_and_eval("&" + var_name.string())
|
|
|
|
return per_cpu(var_ptr, cpu)
|
|
|
|
|
|
|
|
|
|
|
|
PerCpu()
|
2015-02-18 00:47:24 +03:00
|
|
|
|
|
|
|
|
|
|
|
class LxCurrentFunc(gdb.Function):
|
|
|
|
"""Return current task.
|
|
|
|
|
|
|
|
$lx_current([CPU]): Return the per-cpu task variable for the given CPU
|
|
|
|
number. If CPU is omitted, the CPU of the current context is used."""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(LxCurrentFunc, self).__init__("lx_current")
|
|
|
|
|
|
|
|
def invoke(self, cpu=-1):
|
|
|
|
var_ptr = gdb.parse_and_eval("¤t_task")
|
|
|
|
return per_cpu(var_ptr, cpu).dereference()
|
|
|
|
|
|
|
|
|
|
|
|
LxCurrentFunc()
|