Skip to content

Commit a22132f

Browse files
authored
Merge pull request #304 from paulgazz/dev/kextractlinux-llvm-support
Fix klocalizer's tristate modeling issues and enable support for clang/llvm configs
2 parents 5275654 + 523c324 commit a22132f

5 files changed

Lines changed: 34 additions & 7 deletions

File tree

kmax/arch.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,7 @@ def get_missing_kconfig_file_messages(make_stderr: str) -> list:
789789
kextract_version=kextract_module_versions.pop() # pop the next version to try
790790
command = [ "kextractlinux", self.name, kextract_file, "--module-version", kextract_version]
791791
self.__logger.debug("Running kextract tool to generate kextract (module version: %s)." % kextract_version)
792+
self.__logger.debug(f"{" ".join(command)}")
792793
_, ke_stderr_bytes, ret_code = self.__run_command(command, cwd=self.__linux_ksrc)
793794
if ret_code == 0:
794795
break
@@ -956,7 +957,6 @@ def generate_kclause(self):
956957

957958
command = ["kclause", "--remove-orphaned-nonvisible" ]
958959
if self.__kclause_args != None: command = command + self.__kclause_args
959-
# TODO: disable tristate handling when requested, i.e., for kismet
960960
self.__logger.debug("Running kclause tool to generate kclause formulas.")
961961
proc_stdout, _, ret_code = self.__run_command(command, self.__kextract.encode(), capture_stderr=False)
962962

kmax/kclause

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,7 @@ if __name__ == '__main__':
11281128
sys.stderr.write("%s has no final expression\n" % (var))
11291129

11301130
if not disable_tristate_support and var in need_tristate_values and var in bool_types.keys() and bool_types[var] == "tristate":
1131+
# if not disable_tristate_support and var in bool_types.keys() and bool_types[var] == "tristate":
11311132
config_on_iff_y_xor_m = biimplication(var, xor(tristate_config_gen(var, "y"), tristate_config_gen(var, "m")))
11321133
# print(config_on_iff_y_xor_m)
11331134
convert_and_add_clause(var, config_on_iff_y_xor_m)

kmax/kextractlinux

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,28 @@ if __name__ == '__main__':
7575
if not os.path.isdir(archdir):
7676
sys.stderr.write("Architecture directory not available \"%s\", so not attempting kextractlinux.\n" % (archdir))
7777
exit(2)
78-
args.extend([ "-e", "ARCH=%s" % (arch), "-e", "SRCARCH=%s" % (srcarch), "-e", "KERNELVERSION=kcu", "-e", "srctree=./", "-e", "CC=cc", "-e", "LD=ld", "-e", "RUSTC=rustc" ])
78+
args.extend([
79+
"-e", "ARCH=%s" % (arch),
80+
"-e", "SRCARCH=%s" % (srcarch),
81+
"-e", "KERNELVERSION=kcu",
82+
"-e", "srctree=./",
83+
"-e", "RUSTC=rustc"
84+
])
85+
# let the user specify CC and LD, e.g., for clang support
86+
cc_env = os.environ.get("CC", "cc")
87+
ld_env = os.environ.get("LD", "ld")
88+
args.extend([
89+
"-e", f"CC={cc_env}",
90+
"-e", f"LD={ld_env}",
91+
])
92+
# optionally use the LLVM environment variable to support clang/llvm kernel builds
93+
llvm = os.environ.get("LLVM")
94+
if llvm != None:
95+
args.extend([ "-e", f"LLVM={llvm}" ])
96+
# example: LLVM=1 CC="clang -fintegrated-a" LD=ld.lld kextractlinux x86_64 kextract.out --module-version next-20251023
7997
# set arch-specific environment variables
8098
args.extend(arch_specific(arch))
8199
# set the kconfig filename
82100
args.extend([ kconfigfilename ])
101+
sys.stderr.write(f'{" ".join(args)}\n')
83102
kmax.kextractcommon.kextract(module_version, args)

kmax/klocalizer

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,15 +1022,15 @@ def klocalizerCLI():
10221022

10231023
assert allarchs + (len(archs_arg) > 0) + (kclause_file != None) < 2 # at most one can be defined
10241024
if len(archs_arg) > 0:
1025-
archs = [Arch(arch, linux_ksrc=linux_ksrc, arch_dir=get_arch_formulas_dir(formulas, arch), is_kclause_composite=use_composite_kclause_formulas_files, kextract_version=kextract_version, loggerLevel=arch_logger_level) for arch in archs_arg]
1025+
archs = [Arch(arch, linux_ksrc=linux_ksrc, arch_dir=get_arch_formulas_dir(formulas, arch), is_kclause_composite=use_composite_kclause_formulas_files, kextract_version=kextract_version, loggerLevel=arch_logger_level, kclause_args=["--disable-tristate-support"]) for arch in archs_arg]
10261026
elif kclause_file != None:
10271027
# A custom architecture
1028-
arch = Arch(Arch.CUSTOM_ARCH_NAME, kextract_version=kextract_version, loggerLevel=arch_logger_level)
1028+
arch = Arch(Arch.CUSTOM_ARCH_NAME, kextract_version=kextract_version, loggerLevel=arch_logger_level, kclause_args=["--disable-tristate-support"])
10291029
if kextract_file != None: arch.load_kextract(kextract_file, delay_loading=True)
10301030
arch.load_kclause(kclause_file, is_composite=use_composite_kclause_formulas_files, delay_loading=True)
10311031
archs = [arch]
10321032
else: # allarchs is enabled, or if the above are not defined behave as if allarchs
1033-
archs = [Arch(arch, linux_ksrc=linux_ksrc, arch_dir=get_arch_formulas_dir(formulas, arch), is_kclause_composite=use_composite_kclause_formulas_files, kextract_version=kextract_version, loggerLevel=arch_logger_level) for arch in Arch.ARCHS]
1033+
archs = [Arch(arch, linux_ksrc=linux_ksrc, arch_dir=get_arch_formulas_dir(formulas, arch), is_kclause_composite=use_composite_kclause_formulas_files, kextract_version=kextract_version, loggerLevel=arch_logger_level, kclause_args=["--disable-tristate-support"]) for arch in Arch.ARCHS]
10341034

10351035
if kclause_file == None:
10361036
logger.info("Trying the following architectures: %s\n" % " ".join(arch.name for arch in archs))

kmax/klocalizer.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,11 @@ def get_config_file_constraints(config_file):
360360
on = on_pattern.match(line)
361361
if on:
362362
# TODO: use the boolean approximation of tristate if this is disabled by kclause. currently the tristate modeling is kept on by klocalizer for kclause. alternatively use biimplication between options, e.g., CONFIG_A <-> CONFIG_A=y, to support both kclause with and without tristate modeling simultaneously, though this will increase the number of clauses.
363-
# var_name = on.group(1)
364-
var_name = tristate_config_gen(on.group(1), on.group(2))
363+
if False: # tristate_support: # TODO: thread these options throughout kclause and klocalizer for tristate support
364+
var_name = tristate_config_gen(on.group(1), on.group(2))
365+
else: # has tristate support
366+
# TODO: tristate is disabled, because this is not properly integrated with how kclause models tristate options. We likely need to add both the CONFIG_A and CONFIG_A=y boolean predicates to the constraints, because kclause is using both models in parallel as an optimization to reduce the number of clauses.
367+
var_name = on.group(1)
365368
# sys.stderr.write(f"{var_name}\n")
366369
constraint = z3.Bool(var_name)
367370
constraints.append(constraint)
@@ -463,6 +466,9 @@ def get_config_from_model(model: z3.Model, arch: Arch, set_tristate_m, allow_non
463466
tristate_settings = {}
464467
for entry in model:
465468
str_entry = str(entry)
469+
# sys.stderr.write(f"{str(entry)} {str(model[entry])}\n")
470+
# sys.stderr(f"{str(entry)}\n")
471+
# print(f"{str(entry)}\n")
466472
matches = tristate_pattern.match(str_entry)
467473
if matches:
468474
if model[entry]:
@@ -639,6 +645,7 @@ def __approximate_model(self):
639645
solver.add(self.__constraints)
640646

641647
is_sat = solver.check(assumptions) == z3.sat
648+
# breakpoint()
642649
if is_sat:
643650
self.__logger.info("Already satisfiable when constraining with given config. No approximatation needed.\n")
644651
else:

0 commit comments

Comments
 (0)