Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/tools/gdb/pcpu.py
102997 views
1
#
2
# Copyright (c) 2025 Mark Johnston <[email protected]>
3
#
4
# SPDX-License-Identifier: BSD-2-Clause
5
#
6
7
import gdb
8
from freebsd import *
9
10
11
class pcpu(gdb.Function):
12
"""
13
A function to look up PCPU and DPCPU fields by name.
14
15
To look up the value of the PCPU field foo on CPU n, use
16
$PCPU("foo", n). This works for DPCPU fields too. If the CPU ID is
17
omitted, and the currently selected thread is on-CPU, that CPU is
18
used, otherwise an error is raised.
19
"""
20
21
def __init__(self):
22
super(pcpu, self).__init__("PCPU")
23
24
def invoke(self, field, cpuid=-1):
25
if cpuid == -1:
26
cpuid = tdfind(gdb.selected_thread().ptid[2])['td_oncpu']
27
if cpuid == -1:
28
raise gdb.error("Currently selected thread is off-CPU")
29
if cpuid < 0 or cpuid > symval("mp_maxid"):
30
raise gdb.error(f"Currently selected on invalid CPU {cpuid}")
31
pcpu = symval("cpuid_to_pcpu")[cpuid]
32
33
# Are we dealing with a PCPU or DPCPU field?
34
field = field.string()
35
for f in gdb.lookup_type("struct pcpu").fields():
36
if f.name == "pc_" + field:
37
return pcpu["pc_" + field]
38
39
def uintptr_t(val):
40
return val.cast(gdb.lookup_type("uintptr_t"))
41
42
# We're dealing with a DPCPU field. This is handled similarly
43
# to VNET symbols, see vnet.py for comments.
44
pcpu_base = pcpu['pc_dynamic']
45
pcpu_entry = symval("pcpu_entry_" + field)
46
pcpu_entry_addr = uintptr_t(pcpu_entry.address)
47
48
for lf in linker_file_foreach():
49
block = gdb.block_for_pc(lf['ops']['cls']['methods'][0]['func'])
50
elf_file_t = gdb.lookup_type("elf_file_t", block).target()
51
ef = lf.cast(elf_file_t)
52
53
file_type = lf['ops']['cls']['name'].string()
54
if file_type == "elf64":
55
start = uintptr_t(ef['pcpu_start'])
56
if start == 0:
57
continue
58
end = uintptr_t(ef['pcpu_stop'])
59
base = uintptr_t(ef['pcpu_base'])
60
elif file_type == "elf64_obj":
61
for i in range(ef['nprogtab']):
62
pe = ef['progtab'][i]
63
if pe['name'].string() == "set_pcpu":
64
start = uintptr_t(pe['origaddr'])
65
end = start + uintptr_t(pe['size'])
66
base = uintptr_t(pe['addr'])
67
break
68
else:
69
continue
70
else:
71
path = lf['pathname'].string()
72
raise gdb.error(f"{path} has unexpected linker file type {file_type}")
73
74
if pcpu_entry_addr >= start and pcpu_entry_addr < end:
75
obj = gdb.Value(pcpu_base + pcpu_entry_addr - start + base)
76
return obj.cast(pcpu_entry.type.pointer()).dereference()
77
78
79
# Register with gdb.
80
pcpu()
81
82