build: replace argument dispatch and retain source-bound verification
Replace argument recovery with direct build targets. Run host, target, board, coverage, Miri and selected Kani checks while retaining source identities, logs and artifacts, including failed attempts. Keep the PID proof diagnostic exception explicit and match its exact identity alongside passing contract assertions and covers. Validation: final-source verification matrix, assembled workflow tests and documentation build.
This commit is contained in:
1 parent
4953f0a974
commit
62b18d5b2e
26 files changed
+2177
-1052
No files matched your search
@@ -3,11 +3,18 @@
|
||||
|
||||
import importlib.util
|
||||
import json
|
||||
from pathlib import Path
|
||||
import contextlib
|
||||
import io
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
def load_analyzer_module():
|
||||
spec = importlib.util.spec_from_file_location("analyze_fw", "scripts/analyze-fw.py")
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
"analyze_fw", Path(__file__).with_name("analyze-fw.py")
|
||||
)
|
||||
assert spec is not None and spec.loader is not None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(module)
|
||||
@@ -179,6 +186,72 @@ class FirmwareMemoryValidationTests(unittest.TestCase):
|
||||
ANALYZER.sram_control_flow_errors(section, literal)[0],
|
||||
)
|
||||
|
||||
def test_cli_requires_and_checks_executable_sram_code(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
root = Path(temporary)
|
||||
elf, memory = root / "firmware", root / "memory.x"
|
||||
elf.touch()
|
||||
memory.write_text(
|
||||
"MEMORY {\nFLASH : ORIGIN = 0x08000000, LENGTH = 256\nRAM : ORIGIN = 0x20000000, LENGTH = 128\n}\n"
|
||||
)
|
||||
segments = [ANALYZER.LoadSegment(0x08000000, 0x08000000, 0x20, 0x20)]
|
||||
for executable in (False, True):
|
||||
with self.subTest(executable=executable):
|
||||
sections = [
|
||||
ANALYZER.Section(".data", 0x10, 0x20000000, True, executable)
|
||||
]
|
||||
with (
|
||||
patch("sys.argv", ["analyze-fw.py", str(elf), str(memory)]),
|
||||
patch.object(ANALYZER, "llvm_tool", return_value="llvm-tool"),
|
||||
patch.object(
|
||||
ANALYZER,
|
||||
"elf_layout",
|
||||
return_value=(sections, segments),
|
||||
),
|
||||
patch.object(
|
||||
ANALYZER, "run", return_value="20000000: bx lr"
|
||||
) as run,
|
||||
contextlib.redirect_stdout(io.StringIO()),
|
||||
):
|
||||
if executable:
|
||||
ANALYZER.main()
|
||||
self.assertEqual(run.call_count, 2)
|
||||
else:
|
||||
with self.assertRaisesRegex(
|
||||
ValueError,
|
||||
"Flash-operation placement validation failed",
|
||||
):
|
||||
ANALYZER.main()
|
||||
|
||||
def test_cli_rejects_common_memory_bounds(self):
|
||||
with tempfile.TemporaryDirectory() as temporary:
|
||||
elf, memory = Path(temporary) / "firmware", Path(temporary) / "memory.x"
|
||||
elf.touch()
|
||||
memory.write_text(
|
||||
"FLASH : ORIGIN = 0x08000000, LENGTH = 256\nRAM : ORIGIN = 0x20000000, LENGTH = 128\n"
|
||||
)
|
||||
with (
|
||||
patch(
|
||||
"sys.argv",
|
||||
["analyze-fw.py", str(elf), str(memory)],
|
||||
),
|
||||
patch.object(ANALYZER, "llvm_tool", return_value="llvm-readobj"),
|
||||
patch.object(ANALYZER, "run", return_value=""),
|
||||
patch.object(
|
||||
ANALYZER,
|
||||
"elf_layout",
|
||||
return_value=(
|
||||
[ANALYZER.Section(".data", 0x81, 0x20000000, True, False)],
|
||||
[ANALYZER.LoadSegment(0x20000000, 0x080000FF, 2, 0x81)],
|
||||
),
|
||||
),
|
||||
contextlib.redirect_stdout(io.StringIO()),
|
||||
):
|
||||
with self.assertRaisesRegex(
|
||||
ValueError, "firmware memory validation failed"
|
||||
):
|
||||
ANALYZER.main()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user