libexec/kgdb: Add new modules and install them together with debug info
This change simplifies integration of gdb python scripts with our kernel debugging infrastructure. Rather than putting debugging scripts in /usr/libexec/kgdb, move them to <path-to-kernel-debug-symbols>/gdb, and add a kernel-gdb.py which automatically loads modules from that directory. kernel-gdb.py will be automatically executed by kgdb when loading kernel debug symbols (assuming a default configuration), so one no longer needs to do anything to use these modules. The change also adds a couple of new modules, vnet.py and pcpu.py, for conveniently accessing VNET symbols and PCPU/DPCPU fields, respectively. Note that these require a change to the kernel linker when accessing symbols from a loadable kernel module. sys/tools/gdb/README.txt describes the scheme in more detail and provides some rudiementary documentation for the commands and functions added by these modules. It should be updated when adding new features. sys/tools/gdb/selftest.py can be used to do some primitive testing of the modules. All it does is execute a number of gdb commands making use of commands and functions added by these modules. The developer is expected to verify that the commands complete without errors and that the output looks sane. Discussed with: kp, avg, jhb, glebius MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D50825
This commit is contained in:
@@ -10,7 +10,6 @@ SUBDIR= ${_atf} \
|
||||
flua \
|
||||
getty \
|
||||
${_hyperv} \
|
||||
kgdb \
|
||||
${_mail.local} \
|
||||
${_makewhatis.local} \
|
||||
${_mknetid} \
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
FILESDIR?= /usr/libexec/kgdb
|
||||
|
||||
FILES= acttrace.py
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
@@ -1,63 +0,0 @@
|
||||
#-
|
||||
# Copyright (c) 2022 The FreeBSD Foundation
|
||||
#
|
||||
# This software was developed by Mark Johnston under sponsorship from the
|
||||
# FreeBSD Foundation.
|
||||
#
|
||||
|
||||
import gdb
|
||||
|
||||
|
||||
def symval(name):
|
||||
return gdb.lookup_global_symbol(name).value()
|
||||
|
||||
|
||||
def tid_to_gdb_thread(tid):
|
||||
for thread in gdb.inferiors()[0].threads():
|
||||
if thread.ptid[2] == tid:
|
||||
return thread
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def all_pcpus():
|
||||
mp_maxid = symval("mp_maxid")
|
||||
cpuid_to_pcpu = symval("cpuid_to_pcpu")
|
||||
|
||||
cpu = 0
|
||||
while cpu <= mp_maxid:
|
||||
pcpu = cpuid_to_pcpu[cpu]
|
||||
if pcpu:
|
||||
yield pcpu
|
||||
cpu = cpu + 1
|
||||
|
||||
|
||||
class acttrace(gdb.Command):
|
||||
def __init__(self):
|
||||
super(acttrace, self).__init__("acttrace", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
# Save the current thread so that we can switch back after.
|
||||
curthread = gdb.selected_thread()
|
||||
|
||||
for pcpu in all_pcpus():
|
||||
td = pcpu['pc_curthread']
|
||||
tid = td['td_tid']
|
||||
|
||||
gdb_thread = tid_to_gdb_thread(tid)
|
||||
if gdb_thread is None:
|
||||
print("failed to find GDB thread with TID {}".format(tid))
|
||||
else:
|
||||
gdb_thread.switch()
|
||||
|
||||
p = td['td_proc']
|
||||
print("Tracing command {} pid {} tid {} (CPU {})".format(
|
||||
p['p_comm'], p['p_pid'], td['td_tid'], pcpu['pc_cpuid']))
|
||||
gdb.execute("bt")
|
||||
print()
|
||||
|
||||
curthread.switch()
|
||||
|
||||
|
||||
# Registers the command with gdb, doesn't do anything.
|
||||
acttrace()
|
||||
Reference in New Issue
Block a user