quebex

A software analysis framework built around the QBE intermediate language

git clone https://git.8pit.net/quebex.git

 1-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>
 2--
 3-- SPDX-License-Identifier: GPL-3.0-only
 4
 5module Util where
 6
 7import Data.Bifunctor (second)
 8import Data.List (find)
 9import Data.Word (Word64)
10import Language.QBE (Program, globalFuncs, parse)
11import Language.QBE.Backend.Store qualified as ST
12import Language.QBE.Backend.Tracer qualified as ST
13import Language.QBE.Backend.Tracer qualified as T
14import Language.QBE.Simulator (execFunc)
15import Language.QBE.Simulator.Concolic.Expression qualified as CE
16import Language.QBE.Simulator.Concolic.State (mkEnv, run)
17import Language.QBE.Simulator.Default.Expression qualified as DE
18import Language.QBE.Simulator.Explorer (defSolver, explore, newEngine)
19import Language.QBE.Simulator.Expression qualified as E
20import Language.QBE.Simulator.Symbolic.Expression qualified as SE
21import Language.QBE.Types qualified as QBE
22import SimpleBV qualified as SMT
23
24parseProg :: String -> IO Program
25parseProg input =
26  case parse "" input of
27    Left e -> fail $ "Unexpected parsing error: " ++ show e
28    Right r -> pure r
29
30findFunc :: Program -> QBE.GlobalIdent -> QBE.FuncDef
31findFunc prog funcName =
32  case find (\f -> QBE.fName f == funcName) (globalFuncs prog) of
33    Just x -> x
34    Nothing -> error $ "Unknown function: " ++ show funcName
35
36-- TODO: Code duplication with quebex/test/Simulator.hs
37parseAndExec :: QBE.GlobalIdent -> [CE.Concolic DE.RegVal] -> String -> IO ST.ExecTrace
38parseAndExec funcName params input = do
39  prog <- parseProg input
40  let func = findFunc prog funcName
41  env <- mkEnv prog 0 128 Nothing
42  fst <$> run env (execFunc func params)
43
44unconstrained :: SMT.Solver -> Word64 -> String -> QBE.BaseType -> IO (CE.Concolic DE.RegVal)
45unconstrained solver initCon name ty = do
46  symbolic <- SMT.declareBV solver name $ QBE.baseTypeBitSize ty
47  let concrete = E.fromLit (QBE.Base ty) initCon
48  pure $ CE.Concolic concrete (Just $ SE.fromSExpr symbolic)
49
50explore' :: Program -> QBE.FuncDef -> [(String, QBE.BaseType)] -> IO [(ST.Assign, T.ExecTrace)]
51explore' prog entry params = do
52  engine <- newEngine <$> defSolver
53  defEnv <- mkEnv prog 0 128 Nothing
54  explore engine defEnv entry $
55    map (second QBE.Base) params