forked from ulfalizer/Kconfiglib
-
Notifications
You must be signed in to change notification settings - Fork 4
/
list_undefined.py
145 lines (118 loc) · 4.74 KB
/
list_undefined.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# Prints a list of symbols that are referenced in the Kconfig files of some
# architecture but not defined by the Kconfig files of any architecture.
#
# A Kconfig file might be shared between many architectures and legitimately
# reference undefined symbols for some of them, but if no architecture defines
# the symbol, it usually indicates a problem or potential cleanup.
#
# This script could be sped up a lot if needed. See the comment near the
# nodes_referencing_sym() call.
#
# Run with the following command in the kernel root:
#
# $ python(3) Kconfiglib/examples/list_undefined.py
#
# Example output:
#
# Registering defined and undefined symbols for all arches
# Processing mips
# Processing ia64
# Processing metag
# ...
#
# Finding references to each undefined symbol
# Processing mips
# Processing ia64
# Processing metag
# ...
#
# The following globally undefined symbols were found, listed here
# together with the locations of the items that reference them.
# References might come from enclosing menus and ifs.
#
# ARM_ERRATA_753970: arch/arm/mach-mvebu/Kconfig:56, arch/arm/mach-mvebu/Kconfig:39
# SUNXI_CCU_MP: drivers/clk/sunxi-ng/Kconfig:14
# SUNXI_CCU_DIV: drivers/clk/sunxi-ng/Kconfig:14
# AC97: sound/ac97/Kconfig:6
# ...
from kconfiglib import Kconfig
# Reuse a function from the find_symbol.py example
from find_symbol import nodes_referencing_sym
import os
import subprocess
# Referenced inside the Kconfig files
os.environ["KERNELVERSION"] = str(
subprocess.check_output(("make", "kernelversion")).decode("utf-8").rstrip()
)
def all_arch_srcarch_pairs():
"""
Generates all valid (ARCH, SRCARCH) tuples for the kernel, corresponding to
different architectures. SRCARCH holds the arch/ subdirectory.
"""
for srcarch in os.listdir("arch"):
# Each subdirectory of arch/ containing a Kconfig file corresponds to
# an architecture
if os.path.exists(os.path.join("arch", srcarch, "Kconfig")):
yield (srcarch, srcarch)
# Some architectures define additional ARCH settings with ARCH != SRCARCH
# (search for "Additional ARCH settings for" in the top-level Makefile)
yield ("i386", "x86")
yield ("x86_64", "x86")
yield ("sparc32", "sparc")
yield ("sparc64", "sparc")
yield ("sh64", "sh")
yield ("tilepro", "tile")
yield ("tilegx", "tile")
yield ("um", "um")
def all_arch_srcarch_kconfigs():
"""
Generates Kconfig instances for all the architectures in the kernel
"""
for arch, srcarch in all_arch_srcarch_pairs():
print(" Processing " + arch)
os.environ["ARCH"] = arch
os.environ["SRCARCH"] = srcarch
# um (User Mode Linux) uses a different base Kconfig file
yield Kconfig("Kconfig" if arch != "um" else "arch/x86/um/Kconfig",
warn=False)
print("Registering defined and undefined symbols for all arches")
# Sets holding the names of all defined and undefined symbols, for all
# architectures
defined = set()
undefined = set()
for kconf in all_arch_srcarch_kconfigs():
for name, sym in kconf.syms.items():
if sym.nodes:
# If the symbol has a menu node, it is defined
defined.add(name)
else:
# Undefined symbol. We skip some of the uninteresting ones.
# Predefined
if name == "UNAME_RELEASE":
continue
# Due to how Kconfig works, integer literals show up as symbols
# (from e.g. 'default 1'). Skip those.
try:
int(name, 0)
continue
except ValueError:
pass
# Interesting undefined symbol
undefined.add(name)
print("\nFinding references to each undefined symbol")
# Maps each globally undefined symbol to the locations of the items (symbols,
# choices, menus, ifs) that reference it
undef_sym_refs = [(name, set()) for name in undefined - defined]
for kconf in all_arch_srcarch_kconfigs():
for name, refs in undef_sym_refs:
# This means that we search the entire configuration tree for each
# undefined symbol, which is terribly inefficient. We could speed
# things up by tweaking nodes_referencing_sym() to compare each symbol
# to multiple symbols while walking the configuration tree.
for node in nodes_referencing_sym(kconf.top_node, name):
refs.add("{}:{}".format(node.filename, node.linenr))
print("\nThe following globally undefined symbols were found, listed here\n"
"together with the locations of the items that reference them.\n"
"References might come from enclosing menus and ifs.\n")
for name, refs in undef_sym_refs:
print(" {}: {}".format(name, ", ".join(refs)))