Skip to content

Commit ef80d6e

Browse files
authored
Merge pull request #96 from marcosps/fix-gcc-args-catching-issue
extract: Get gcc args by using compile_commands.json
2 parents 9ff646e + 1f6ebdd commit ef80d6e

File tree

2 files changed

+74
-40
lines changed

2 files changed

+74
-40
lines changed

klpbuild/plugins/extractor.py

+28-39
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Copyright (C) 2021-2024 SUSE
44
# Author: Marcos Paulo de Souza <[email protected]>
55

6-
import concurrent.futures
6+
from concurrent.futures import ThreadPoolExecutor
77
import difflib as dl
88
import json
99
import logging
@@ -158,8 +158,7 @@ def get_make_cmd(out_dir, cs, filename, odir, sdir):
158158
elif shutil.which("gcc-7"):
159159
cc = "gcc-7"
160160
else:
161-
logging.error("Only gcc12 or higher are available, and it's problematic with kernel sources")
162-
raise
161+
raise RuntimeError("Only gcc12 or higher are available, and it's problematic with kernel sources")
163162

164163
make_args = [
165164
"make",
@@ -187,9 +186,8 @@ def get_make_cmd(out_dir, cs, filename, odir, sdir):
187186
f.write(str(completed))
188187
f.write("\n")
189188
f.flush()
190-
except subprocess.CalledProcessError as exc:
191-
logging.error(f"Failed to run make for {cs.name()} ({cs.kernel}). Check file {str(log_path)} for more details.")
192-
raise exc
189+
except Exception:
190+
raise RuntimeError(f"Failed to run make for {cs.name()} ({cs.kernel}). Check file {str(log_path)} for more details.")
193191

194192
# 15.4 onwards changes the regex a little: -MD -> -MMD
195193
# 15.6 onwards we don't have -isystem.
@@ -210,9 +208,7 @@ def get_make_cmd(out_dir, cs, filename, odir, sdir):
210208
f.flush()
211209

212210
if not result:
213-
logging.error(f"Failed to get the kernel cmdline for file {str(ofname)} in {cs.name()}. "
214-
f"Check file {str(log_path)} for more details.")
215-
return None
211+
raise RuntimeError(f"Failed to get the kernel cmdline for file {str(ofname)} in {cs.name()}. Check file {str(log_path)} for more details.")
216212

217213
ret = Extractor.process_make_output(result.group(1))
218214

@@ -230,11 +226,8 @@ def get_make_cmd(out_dir, cs, filename, odir, sdir):
230226

231227
return ret
232228

233-
return None
234-
235-
236-
# Generate the list of exported symbols
237229
def get_symbol_list(self, out_dir):
230+
# Generate the list of exported symbols
238231
exts = []
239232

240233
for ext_file in ["fun_exts", "obj_exts"]:
@@ -341,24 +334,25 @@ def apply_all_patches(self, cs, fil):
341334
if not patched:
342335
raise RuntimeError(f"{cs.name()}({cs.kernel}): Failed to apply patches. Aborting")
343336

344-
345-
346337
def get_cmd_from_json(self, cs, fname):
347-
cc_file = Path(cs.get_obj_dir(), "compile_commands.json")
348-
# FIXME: compile_commands.json that is packaged with SLE/openSUSE
349-
# doesn't quite work yet, so don't use it yet.
350-
return None
338+
cc_file = cs.get_obj_dir()/"compile_commands.json"
339+
340+
# Older codestreams doens't support compile_commands.json, so use make for them
341+
if not cc_file.exists():
342+
return None
351343

352344
with open(cc_file) as f:
353345
buf = f.read()
354346
data = json.loads(buf)
355347
for d in data:
356348
if fname in d["file"]:
357349
output = d["command"]
358-
return Extractor.process_make_output(output)
350+
# The arguments found on the file point to .., since they are generated
351+
# when the kernel is compiled. Replace the .. by the codestream kernel source
352+
# directory since klp-ccp needs to reach the files
353+
return Extractor.process_make_output(output).replace("..", str(cs.get_src_dir()))
359354

360-
logging.error(f"Couldn't find cmdline for {fname}. Aborting")
361-
return None
355+
raise RuntimeError(f"Couldn't find cmdline for {fname} on {str(cc_file)}. Aborting")
362356

363357
def cmd_args(self, cs, fname, out_dir, fdata, cmd):
364358
lp_out = Path(out_dir, cs.lp_out_file(self.lp_name, fname))
@@ -439,13 +433,10 @@ def process(self, args):
439433
# Make can regenerate fixdep for each file being processed per
440434
# codestream, so avoid the TXTBUSY error by serializing the 'make -sn'
441435
# calls. Make is pretty fast, so there isn't a real slow down here.
442-
with self.make_lock:
443-
cmd = self.get_cmd_from_json(cs, fname)
444-
if not cmd:
445-
cmd = Extractor.get_make_cmd(out_dir, cs, fname, odir, sdir)
446-
436+
cmd = self.get_cmd_from_json(cs, fname)
447437
if not cmd:
448-
raise
438+
with self.make_lock:
439+
cmd = Extractor.get_make_cmd(out_dir, cs, fname, odir, sdir)
449440

450441
args, lenv = self.cmd_args(cs, fname, out_dir, fdata, cmd)
451442

@@ -462,9 +453,8 @@ def process(self, args):
462453
f.flush()
463454
try:
464455
subprocess.run(args, cwd=odir, stdout=f, stderr=f, env=lenv, check=True)
465-
except:
466-
logging.error(f"Error when processing {cs.name()}:{fname}. Check file {out_log} for details.")
467-
raise
456+
except Exception as exc:
457+
raise RuntimeError(f"Error when processing {cs.name()}:{fname}. Check file {out_log} for details.") from exc
468458

469459
cs.files[fname]["ext_symbols"] = self.get_symbol_list(out_dir)
470460

@@ -511,15 +501,14 @@ def run(self):
511501
logging.info(f"\nGenerating livepatches for {len(args)} file(s) using {self.workers} workers...")
512502
logging.info("\t\tCodestream\tFile")
513503

514-
with concurrent.futures.ThreadPoolExecutor(max_workers=self.workers) as executor:
515-
results = executor.map(self.process, args)
504+
with ThreadPoolExecutor(max_workers=self.workers) as executor:
516505
try:
517-
for result in results:
518-
if result:
519-
logging.error(f"{cs}: {result}")
520-
except:
521-
executor.shutdown()
522-
sys.exit(1)
506+
futures = executor.map(self.process, args)
507+
for future in futures:
508+
if future:
509+
logging.error(future)
510+
except Exception as exc:
511+
raise RuntimeError(str(exc)) from exc
523512

524513
# Save the ext_symbols set by execute
525514
store_codestreams(self.lp_name, working_cs)

tests/test_extract.py

+46-1
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
# Copyright (C) 2021-2024 SUSE
44
# Author: Marcos Paulo de Souza
55

6+
import json
67
import inspect
78
import logging
9+
import pytest
810

911
from klpbuild.plugins.extractor import Extractor
1012
from klpbuild.plugins.setup import setup
13+
from klpbuild.klplib.codestreams_data import load_codestreams
1114
from klpbuild.klplib import utils
1215

16+
import tests.utils as tests_utils
1317

1418
def test_detect_file_without_ftrace_support(caplog):
1519
lp = "bsc_" + inspect.currentframe().f_code.co_name
@@ -29,8 +33,49 @@ def test_detect_file_without_ftrace_support(caplog):
2933
}
3034
setup(**setup_args)
3135

32-
3336
with caplog.at_level(logging.WARNING):
3437
Extractor(lp_name=lp, lp_filter=cs, apply_patches=False, avoid_ext=[]).run()
3538

3639
assert "lib/seq_buf.o is not compiled with livepatch support (-pg flag)" in caplog.text
40+
41+
42+
def test_compile_commands_enoent():
43+
"""
44+
Check if the extraction fails when a file isn't found on
45+
compile_commands.json file
46+
"""
47+
48+
lp = "bsc_" + inspect.currentframe().f_code.co_name
49+
cs = "15.6u8"
50+
51+
setup_args = {
52+
"lp_name": lp,
53+
"lp_filter": cs,
54+
"no_check": False,
55+
"archs": [utils.ARCH],
56+
"cve": None,
57+
"conf": "CONFIG_HID",
58+
"module": "vmlinux",
59+
"file_funcs": [["drivers/hid/hid-core.c", "hid_alloc_report_buf"]],
60+
"mod_file_funcs": [],
61+
"conf_mod_file_funcs": []
62+
}
63+
setup(**setup_args)
64+
65+
# rename the entry on files to a filename that doesn't exists (hid_core.c)
66+
data = tests_utils.get_codestreams_file(lp)
67+
file_funcs = data["codestreams"][cs]["files"].pop("drivers/hid/hid-core.c")
68+
data["codestreams"][cs]["files"]["drivers/hid/hid_core.c"] = file_funcs
69+
70+
# write back the changed codestreams.json file
71+
with open(utils.get_workdir(lp)/"codestreams.json", "r+") as f:
72+
f.seek(0)
73+
f.write(json.dumps(data, indent=4))
74+
f.truncate()
75+
76+
# reload the codestreams after the change
77+
load_codestreams(lp)
78+
79+
# Now it should fail with hid_core.c that doesn't exists on compile_commands.json
80+
with pytest.raises(RuntimeError, match=r"Couldn't find cmdline for drivers/hid/hid_core.c on.*compile_commands.json. Aborting"):
81+
Extractor(lp_name=lp, lp_filter=cs, apply_patches=False, avoid_ext=[]).run()

0 commit comments

Comments
 (0)